Как создать собственный домен для assert/matcher в споке или хамкресте
Я пытаюсь написать собственный домен, связанный с assert / matcher, в spock или hamcrest, но я не уверен, что делать дальше.
Я пытался написать собственный Matcher в Hamcrest, но пока это привело меня только к частичному решению.
Я ищу некоторые указания относительно того, каким будет правильный курс в этом сценарии.
Доменные объекты:
- ResultMap имеет объект Map
- с каждым ILine связан один INodeResult. - IResult имеет 4 (Google Guava) мультикартных объекта, которые необходимо проверить.
То, что я хотел бы сделать в моем тесте на спок, выглядит примерно так:
expect:
that actualResultMap, matchesInAnyOrder(expectedResultMap)
or
that actualResultMap, matches(expectedResultMap) // Will only match if everything is in the same order.
Внутренний код будет затем оценивать каждую запись и делать соответствующие тесты и на внутренних объектах.
До сих пор мне удалось написать часть кода, которая оценивает один набор мультикарты, но я не уверен, как связать мои тесты.
Custom Matcher:
package com.ps.DE.Test.CustomMatcher
import org.hamcrest.BaseMatcher
class MultimapMatcher {
/**
* Checks all the entries in a Multimap with another
* @param expected
* @return Shows the failure only if the entries do not match or are not in the same order
*/
static hasAllInOrder(final com.google.common.collect.Multimap expected){
[
matches: { actual ->
for(key in actual.keySet()){
if (actual.get(key) != expected.get(key)){
return false
}
}
return true
},
describeTo: { description ->
description.appendText("MultiMap entries to be ${expected}")
},
describeMismatch: { actual, description ->
description.appendText("were ${actual}")
}
] as BaseMatcher
}
/**
* Checks all the entries in a Multimap with another
* @param expected
* @return Shows the failure only if the entries do not match
*/
static hasAllInAnyOrder(final com.google.common.collect.Multimap expected){
[
matches: { actual ->
for(key in actual.keySet()){
if (!actual.get(key).containsAll(expected.get(key))) {
return false
}
}
return true
},
describeTo: { description ->
description.appendText("MultiMap entries to be ${expected}")
},
describeMismatch: { actual, description ->
description.appendText("were ${actual}")
}
] as BaseMatcher
}
}
Тестирование пользовательского Matcher:
package com.ps.DE.Test.CustomMatcher
import com.google.common.collect.ArrayListMultimap
import com.google.common.collect.Multimap
import spock.lang.Specification
import static com.ps.DE.Test.CustomMatcher.MultimapMatcher.hasAllInAnyOrder
import static com.ps.DE.Test.CustomMatcher.MultimapMatcher.hasAllInOrder
import static org.hamcrest.Matchers.not
import static spock.util.matcher.HamcrestSupport.that
class MultimapMatcherSpec extends Specification {
def "Test hasAllInOrder"() {
def actual = ArrayListMultimap.create();
// Adding some key/value
actual.put "Fruits", "Apple"
actual.put "Fruits", "Banana"
actual.put "Fruits", "Pear"
actual.put "Vegetables", "Carrot"
Multimap<String, String> expected = ArrayListMultimap.create();
// Adding some key/value
expected.put("Fruits", "Apple");
expected.put("Fruits", "Banana");
expected.put("Fruits", "Pear");
expected.put("Vegetables", "Carrot");
expect:
that actual, hasAllInAnyOrder(expected)
that actual, hasAllInOrder(expected)
}
def "Test hasAllInAnyOrder"() {
Multimap<String, String> actual = ArrayListMultimap.create();
// Adding some key/value
actual.put("Fruits", "Apple");
actual.put("Fruits", "Banana");
actual.put("Fruits", "Pear");
actual.put("Vegetables", "Carrot");
Multimap<String, String> expected = ArrayListMultimap.create();
// Adding some key/value
expected.put("Fruits", "Banana");
expected.put("Fruits", "Apple");
expected.put("Fruits", "Pear");
expected.put("Vegetables", "Carrot");
expect:
that actual, hasAllInAnyOrder(expected)
that actual, not(hasAllInOrder(expected))
}
}
Любая помощь или руководство будут с благодарностью.
1 ответ
Зачем вообще нужны нестандартные совпадения? Возможно, Спок и Groovy достаточно мощные, чтобы удовлетворить ваши потребности без специальных сопоставителей.
Чтобы соответствовать два Multimap
объекты имеют одинаковое содержимое в том же порядке, что достаточно сделать:
expected:
actual == expected
Есть ли польза в добавлении гораздо большего количества кода к тому же утверждению?
Для сравнения в любом порядке это немного сложнее, но достаточно добавить метод сортировки (может быть извлечен и использован повторно в других тестовых классах). Это может выглядеть так:
expected:
sortValues(actual) == sortValues(expected)
и сам метод:
static Map<String, Collection<String>> sortValues(Multimap<String, String> multimap) {
multimap.asMap().collectEntries {
[it.key, it.value.sort(false)]
}
}
Возможно для лучшей читабельности спецификации sortValues()
может иметь имя anyOrder()
что сделало бы утверждение похожим на:
expect:
anyOrder(actual) == anyOrder(expected)
Внутренний код будет затем оценивать каждую запись и делать соответствующие тесты и на внутренних объектах.
Эта часть может быть реализована equals
метод для каждого сравниваемого типа объекта.