Groovy 2.x和Mockito没有很好地融合在一起

时间:2014-12-06 18:43:57

标签: unit-testing groovy jersey jax-rs mockito

我正在尝试为使用Jersey来访问RESTful Web服务的一些代码编写一些单元测试,并使用Mockito来模拟一些东西。这是我的代码:

@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>
}

正如您所看到的,每当mockAddress尝试执行HTTP GET时,我尝试强制Jersey返回WebResource实例。

当这个运行时,我得到:

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)

MyUnitTest.groovy:19是哪一行:

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

关于发生了什么的任何想法?

2 个答案:

答案 0 :(得分:4)

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

正如消息中所描述的那样,模糊性似乎就在哪里。话虽如此,使用Mockito.any()似乎并不合适。我不是Mockito的大用户,因此我不知道使用它的正常使用情况。当我尝试将它与Java一起使用时,我会收到编译错误,因为Mockit.any()将返回Object,并且两个重载方法都不接受Object作为参数。< / p>

话虽如此,您所嘲笑的行为是,当您在get上致电WebResource时,它应该返回Address个对象,因此您会想要传递Address.class(或者在Groovy的情况下Address可能没问题,正如您在上一篇文章中提到的那样)get方法。

应该起作用的东西(至少在我用Java测试时)是这样的:

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);

这应打印出"Hello World"

答案 1 :(得分:0)

这是由于Groovy中的multiple dispatch机制造成的。

只需将CFRunLoopRun()调用的结果转换为要存根的重载方法的参数类型即可。

any()

进口:

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

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

有关this答案,thisthis博客文章的更多详细信息。