In a previous blog post we learned how we can use Hamcrest matchers. We can also create a custom matcher and use it in our Spock specification. Let's create a custom matcher that will check if elements in a list are part of a range.
In the following specification we create the method inRange()
which will return an instance of a Matcher
object. This object must implement a matches()
method and extra methods to format the description when the matcher fails. We use Groovy's support to create a Map and turn it into an instance of BaseMatcher
.
// File: SampleSpecification.groovy package com.mrhaki.spock @Grab('org.hamcrest:hamcrest-all:1.3') import static org.hamcrest.Matchers.* import org.hamcrest.* @Grab('org.spockframework:spock-core:0.7-groovy-2.0') import static spock.util.matcher.HamcrestSupport.* import spock.lang.Specification class SampleSpecification extends Specification { def "sample usage of custom hamcrest matcher"() { given: final list = [2,3,4] expect: that list, inRange(0..10) that list, not(inRange(0..3)) } /** * Create custom Hamcrest matcher to check if a list has elements * that are contained in the define range. * * @param range Range to check if elements in the list are in this range. * @return Hamcrest matcher to check if elements in the list are part of the range. */ private inRange(final range) { [ matches: { list -> range.intersect(list) == list }, describeTo: { description -> description.appendText("list be in range ${range}") }, describeMismatch: { list, description -> description.appendValue(list.toListString()).appendText(" was not in range ${range}") } ] as BaseMatcher } }
We can run the specification ($ groovy SampleSpecification.groovy
) and everything should work and all tests must pass.
We change the code to see the description we have added. So we change that list, inRange(0..10)
to that list, inRange(0..3)
. We run the specification again ($ groovy SampleSpecification.groovy
) and look at the output:
JUnit 4 Runner, Tests: 1, Failures: 1, Time: 200 Test Failure: sample usage of custom hamcrest matcher(com.mrhaki.spock.SampleSpecification) Condition not satisfied: that list, inRange(0..3) | | | [2, 3, 4] false Expected: list be in range [0, 1, 2, 3] but: "[2, 3, 4]" was not in range [0, 1, 2, 3] at com.mrhaki.spock.SampleSpecification.sample usage of custom hamcrest matcher(SampleSpecification.groovy:18)
Notice the output shows the text we have defined in the describeTo()
and describeMismatch()
methods.
Code written with Spock 0.7-groovy-0.2.