Spock InteractionBuilder doesn't work with spread (*) operator
Describe the bug
Unable to pass spread operator (*) to interaction verification.
To Reproduce
I have a service that is just a wrapper for another class:
class WrapperClass {
InternalClass internalClass;
public void firstMethod(String firstArg, String secondArg) {
internalClass.firstMethod(firstArg, secondArg);
}
public void secondMethod(String firstArg, String secondArg, long thirdArg) {
internalClass.secondMethod(firstArg, secondArg, thirdArg);
}
}
class InternalClass {
public void firstMethod(String firstArg, String secondArg) {
// do smth
}
public void secondMethod(String firstArg, String secondArg, long thirdArg) {
// do smth
}
}
I am writing the following test that dynamically verifies all wrapper methods:
class WrapperClassTest extends Specification {
def innerClass = Mock(InnerClass)
def wrapper = new WrapperClass(innerClass: innerClass)
@Unroll
def "test #methodName with args #args"() {
when:
wrapper."$methodName"(*args)
then:
1 * innerClass."$methodName"(*args)
where:
methodName | args
'firstMethod' | ['firstArg', 'secondArg']
'secondMethod' | ['firstArg', 'secondArg', 123L]
}
}
But I am getting the following exception:
groovy.lang.MissingMethodException: No signature of method: org.spockframework.mock.runtime.InteractionBuilder.addEqualArg() is applicable for argument types: (java.lang.String, java.lang.String) values: [firstArg, secondArg]
Possible solutions: addEqualArg(java.lang.Object)
Expected behavior
The test should pass.
Actual behavior
Test fails with the following exception:
groovy.lang.MissingMethodException: No signature of method: org.spockframework.mock.runtime.InteractionBuilder.addEqualArg() is applicable for argument types: (java.lang.String, java.lang.String) values: [firstArg, secondArg]
Possible solutions: addEqualArg(java.lang.Object)
Java version
java version "1.8.0_251"
Buildtool version
Gradle 6.5
What operating system are you using
Windows
Dependencies
spock 1.3 - groovy 2.4
Additional context
No response
I am not sure, this is supposed to work, but FWIW, I can confirm that in Spock 2.0 + Groovy 3 the outcome is the same.
Interactions are transformed at compile time and each argument is translated to its own method call, e.g., addEqualArg.
That is why this doesn't work at the moment, since it would have to translate [1, 2] to .addEqualArg(1).addEqualArg(2) instead of .addEqualArg(*args) during runtime. Spock only has special handling for the *_ expression, meaning any arguments.
For now you can use a workaround:
class WrapperClassTest extends Specification {
def innerClass = Mock(InternalClass)
def wrapper = new WrapperClass(internalClass: innerClass)
@Unroll
def "test #methodName with args #args"() {
when:
wrapper."$methodName"(*args)
then:
1 * innerClass."$methodName"(*_) >> { invocationArgs ->
assert invocationArgs == args
}
where:
methodName | args
'firstMethod' | ['firstArg', 'secondArg']
'secondMethod' | ['firstArg', 'secondArg', 123L]
}
}
Thanks, It would help.