java - How to create a custom domain specific assert/matcher in spock or hamcrest -
i trying write custom domain related assert/matcher in spock or hamcrest, not sure how proceed.
i tried writing custom matcher in hamcrest far has led me partial solution.
i looking guidance proper course in scenario be.
domain objects:
- resultmap has object map < iline, iresult > - there 1 inoderesult associated each iline.
- iresult has 4 (google guava) multimap objects need verified.
what in spock test like:
expect: actualresultmap, matchesinanyorder(expectedresultmap) or actualresultmap, matches(expectedresultmap) // match if in same order.
the internal code evaluate each entry , appropriate tests on inner objects well.
so far managed write part of code evaluates 1 set of multimap, not sure how chain tests.
custom matcher:
package com.ps.de.test.custommatcher import org.hamcrest.basematcher class multimapmatcher { /** * checks entries in multimap * @param expected * @return shows failure if entries not match or not in 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 ${expected}") }, describemismatch: { actual, description -> description.appendtext("were ${actual}") } ] basematcher } /** * checks entries in multimap * @param expected * @return shows failure if entries 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 ${expected}") }, describemismatch: { actual, description -> description.appendtext("were ${actual}") } ] basematcher } }
testing custom 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 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 key/value expected.put("fruits", "apple"); expected.put("fruits", "banana"); expected.put("fruits", "pear"); expected.put("vegetables", "carrot"); expect: actual, hasallinanyorder(expected) actual, hasallinorder(expected) } def "test hasallinanyorder"() { multimap<string, string> actual = arraylistmultimap.create(); // adding 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 key/value expected.put("fruits", "banana"); expected.put("fruits", "apple"); expected.put("fruits", "pear"); expected.put("vegetables", "carrot"); expect: actual, hasallinanyorder(expected) actual, not(hasallinorder(expected)) } }
any or guidance appreciated.
why need custom matchers @ all? perhaps, spock , groovy powerful enough fulfil need without custom matchers.
to match 2 multimap
objects have same content in same order enough do:
expected: actual == expected
is there benefit in adding more code same assertion?
for match in order it's bit more tricky it's enough add sorting method (may extracted , reused within other test classes). like:
expected: sortvalues(actual) == sortvalues(expected)
and method itself:
static map<string, collection<string>> sortvalues(multimap<string, string> multimap) { multimap.asmap().collectentries { [it.key, it.value.sort(false)] } }
perhaps better specification readability sortvalues()
may have name anyorder()
make assertion like:
expect: anyorder(actual) == anyorder(expected)
the internal code evaluate each entry , appropriate tests on inner objects well.
this part can implemented equals
method on each object type under comparison.
Comments
Post a Comment