3

I am trying to write some unit tests for some code that uses Jersey to hit a RESTful web service, and am using Mockito to mock out some things. Here's my code:

@Test
void test() {
    given:
    // WebResource is a Jersey/JAX-RS construct.
    WebResource mockResource = Mockito.mock(WebResource)

    // Address.groovy is a POJO from my project.
    Address mockAddress = Mockito.mock(Address)

    // THE NEXT LINE IS WHAT IS THROWING THE EXCEPTION:
    Mockito.when(mockResource.get(Mockito.any())).thenReturn(mockAddress)

    when:
    <omitted for brevity>

    then:
    <omitted for brevity>
}

As you can see, I'm trying to coerce Jersey to return my mockAddress instance whenever the WebResource attempts to do an HTTP GET.

When this runs I get:

groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method com.sun.jersey.api.client.WebResource$$EnhancerByMockitoWithCGLIB$$1c2e51fa#get.
Cannot resolve which method to invoke for [null] due to overlapping prototypes between:
[class com.sun.jersey.api.client.GenericType]
[class java.lang.Class]
    at groovy.lang.MetaClassImpl.chooseMostSpecificParams(MetaClassImpl.java:3031)
    at groovy.lang.MetaClassImpl.chooseMethodInternal(MetaClassImpl.java:2983)
    at groovy.lang.MetaClassImpl.chooseMethod(MetaClassImpl.java:2926)
    at groovy.lang.MetaClassImpl.getMethodWithCachingInternal(MetaClassImpl.java:1203)
    at groovy.lang.MetaClassImpl.createPojoCallSite(MetaClassImpl.java:3130)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.createPojoSite(CallSiteArray.java:129)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:163)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at com.me.myapp.MyUnitTest.test(MyUnitTest.groovy:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    <large stack trace omitted for brevity>
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Where MyUnitTest.groovy:19 is the line:

Mockito.when(mockResource.get(Mockito.any())).thenReturn(mockAddress)

Any ideas as to what is going on?

IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756

2 Answers2

4

WebResource's get() method is overloaded with get(Class) and get(GenericType).

That seems to be where is ambiguity is, as described in the message. That being said, it doesn't really seems appropriate to use Mockito.any(). I'm not a big Mockito user, so I don't know of the normal use cases for using it. When I try to use it with Java, I'll get a compile error, as Mockit.any() will return Object, and neither of the overloaded methods accept Object as an argument.

That being said, the behavior you are mocking, is that when you call get on the WebResource it should return an Address object, so you'll would want to pass Address.class (or Address in the case of Groovy might be OK, as you mentioned in your previous post) to the get method.

Something that should work (at least when I tested with Java) is something like:

WebResource resource = Mockito.mock(WebResource.class);
Address address = Mockito.mock(Address.class);

Mockito.when(resource.get(Address.class)).thenReturn(address);
Mockito.when(address.toString()).thenReturn("Hello World");

Address a = resource.get(Address.class);
System.out.println(a);

This should print out "Hello World"

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
3

This is due to the multiple dispatch mechanism in Groovy.

Just cast the result of the any() call to the type of the overloaded method's parameter you are stubbing.

when(mockResource.get(any() as Address)).thenReturn(mockAddress)

// this also works
when(mockResource.get(any(Address) as Address)).thenReturn(mockAddress)

Imports:

import static org.mockito.ArgumentMatchers.any
import static org.mockito.Mockito.when

More details on this answer, this and this blog posts.

Voicu
  • 16,921
  • 10
  • 60
  • 69
  • The provided links are all about runtime type information and how Groovy program execution and code development is affected by it. – Alexander Stohr Dec 22 '20 at 16:14