Joerg S
Joerg S

Reputation: 5129

Is there a way to get GroovyMock (in Spock) accepting a GString for a String argument?

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

Answers (1)

kriegaex
kriegaex

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

Related Questions