Reputation: 5129
Unfortunately I could not yet find any useful information about this topic.
I have some Spock tests where I need to use a GroovyMock
instead of a Mock
- as of it's support for mocking dynamic methods.
One of the (non-dynamic) method takes a String argument. Sometimes a GString gets passed as an argument to that method. That is working fine in the productive code as well as for a Mock
.
However after switching to a GroovyMock
I got a java.lang.IllegalArgumentException: argument type mismatch
exception pointing me to the following line (see example below):
someClass.someMethod("foo ${1 + 1}")
I did already check whether some of the options available during creation of the GroovyMock
could help. So far I tried the verified
option - which unfortunately did not help. The other options did not even seem to bear the chance to be useful here, so I did not try to use them (and for most of them I would not even have known how to use them).
Please check the following small example for reference:
import spock.lang.Specification
class SomeClass {
String someMethod(String arg) {
return arg
}
}
class TestClass {
SomeClass someClass
String callMethod() {
someClass.someMethod("foo ${1 + 1}")
}
}
class FooSpec extends Specification {
def 'pass String to groovyMock mocked method taking a String argument'() {
given:
TestClass testClass = new TestClass()
SomeClass someClass = GroovyMock() // does not work
// SomeClass someClass = Mock() // test works if used instead of the previous line
testClass.someClass = someClass
when:
testClass.callMethod()
then:
1 * someClass.someMethod(_)
}
}
Upvotes: 1
Views: 631
Reputation: 67317
Good catch! I can confirm this behaviour in both Spock 1.3-groovy-2.5
and 2.0-M3-groovy-3.0
. I think it would make sense to create a Spock issue and link back to this question from there.
I have debugged into the issue and printed the stack trace before it gets "cleaned up" for test error reporting. You might want to add it to the new issue:
java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:104)
at org.spockframework.mock.runtime.GroovyMockMetaClass.doInvokeMethod(GroovyMockMetaClass.java:83)
at org.spockframework.mock.runtime.GroovyMockMetaClass.invokeMethod(GroovyMockMetaClass.java:39)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:41)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127)
at de.scrum_master.stackoverflow.q63797837.TestClass.callMethod(FooSpec.groovy:15)
at de.scrum_master.stackoverflow.q63797837.TestClass$callMethod.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:119)
at de.scrum_master.stackoverflow.q63797837.FooSpec.$spock_feature_0_0(FooSpec.groovy:28)
... 34 more
Update: One more finding: If you change the target method signature to String someMethod(GString arg)
, the test passes with the GroovyMock. So possibly the problem is somehow connected to casting the GString
used in someClass.someMethod("foo ${1 + 1}")
into a String
.
Update 2020-09-16: A couple of days ago I have created Spock issue #1216 on your behalf because you ignored my advice to do so by yourself. The bug has been fixed already and I expect it to be available in the next 2.0 milestone release and of course also in the final release.
Upvotes: 4