When we mock or stub methods we can use the method arguments passed to the method in the response for the mocked or stubbed method. We must write a closure after the rightShift operator (>>) and the closure arguments will resemble the arguments of the mocked or stubbed method. Alternatively we can use a single non-typed argument in the closure and this will contains the method argument list.
Let's create a specification where we use this feature. In the following sample we use a mock for the AgeService used in the class under test. The method allowedMaxTime() is invoked by the class under test and basically should return the maximum hour of the day a show can be broadcasted. In our specification we use the name of the show to return different values during the test.
package com.mrhaki.spock
@Grab('org.spockframework:spock-core:0.7-groovy-2.0')
import spock.lang.*
class SampleSpec extends Specification {
final ClassUnderTest classUnderTest = new ClassUnderTest()
@Unroll
def "show #name with start time 21h is #expected to show"() {
setup:
final AgeService ageService = Mock()
classUnderTest.ageService = ageService
when:
final boolean allowed = classUnderTest.listing(new Show(name: name, startTime: 21))
then:
1 * ageService.allowedMaxTime(_ as Show) >> { Show show ->
show.name.toLowerCase().contains('kids') ? 10 : 23
}
// Alternative syntax with a non-typed closure argument:
//1 * ageService.allowedMaxTime(_ as Show) >> { arguments ->
// arguments[0].name.toLowerCase().contains('kids') ? 10 : 23
//}
allowed == expected
where:
name || expected
'Kids rules' || false
'Sports united' || true
}
}
/* Supporting classes and interface */
class ClassUnderTest {
AgeService ageService
boolean listing(final Show show) {
final int hour = ageService.allowedMaxTime(show)
show.startTime <= hour
}
}
interface AgeService {
int allowedMaxTime(Show show)
}
@groovy.transform.Canonical
class Show {
String name
int startTime
}
Code written with Spock 0.7-groovy-2.0.