3 Stimmen

Groovy 2.x und Mockito vertragen sich nicht gut.

Ich versuche, einige Unit-Tests für einige Codezeilen zu schreiben, die Jersey verwenden, um einen RESTful-Webservice zu erreichen, und verwende Mockito, um einige Dinge zu mocken. Hier ist mein Code:

@Test
void test() {
    gegeben:
    // WebResource ist ein Jersey/JAX-RS-Konstrukt.
    WebResource mockResource = Mockito.mock(WebResource)

    // Address.groovy ist ein POJO aus meinem Projekt.
    Address mockAddress = Mockito.mock(Address)

    // DIE NÄCHSTE LINIE WIRFT DIE AUSNAHME AUS:
    Mockito.when(mockResource.get(Mockito.any())).thenReturn(mockAddress)

    wenn:

    dann:

}

Wie Sie sehen können, versuche ich Jersey dazu zu bringen, meine mockAddress-Instanz zurückzugeben, wenn der WebResource einen HTTP GET durchführt.

Wenn dies ausgeführt wird, erhalte ich:

groovy.lang.GroovyRuntimeException: Mehrdeutige Methodenüberladung für Methode com.sun.jersey.api.client.WebResource$$EnhancerByMockitoWithCGLIB$$1c2e51fa#get.
Kann nicht auflösen, welche Methode für [null] aufgrund von überlappenden Prototypen zwischen bestimmt werden soll:
[class com.sun.jersey.api.client.GenericType]
[class java.lang.Class]
    bei groovy.lang.MetaClassImpl.chooseMostSpecificParams(MetaClassImpl.java:3031)
    bei groovy.lang.MetaClassImpl.chooseMethodInternal(MetaClassImpl.java:2983)
    bei groovy.lang.MetaClassImpl.chooseMethod(MetaClassImpl.java:2926)
    bei groovy.lang.MetaClassImpl.getMethodWithCachingInternal(MetaClassImpl.java:1203)
    bei groovy.lang.MetaClassImpl.createPojoCallSite(MetaClassImpl.java:3130)
    bei org.codehaus.groovy.runtime.callsite.CallSiteArray.createPojoSite(CallSiteArray.java:129)
    bei org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:163)
    bei org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    bei org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    bei org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    bei com.me.myapp.MyUnitTest.test(MyUnitTest.groovy:19)
    bei sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    bei sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    bei sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

    bei org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    bei org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Wo MyUnitTest.groovy:19 die Zeile ist:

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

Ideen, was los ist?

4voto

Paul Samsotha Punkte 197171

Die Methode get() von WebResource ist überladen mit get(Class) und get(GenericType).

Dort scheint die Ambiguität zu liegen, wie in der Nachricht beschrieben. Das heißt, es scheint nicht wirklich angemessen zu sein, Mockito.any() zu verwenden. Ich bin kein großer Mockito-Benutzer, also kenne ich die normalen Anwendungsfälle nicht. Wenn ich versuche, es mit Java zu verwenden, erhalte ich einen Kompilierfehler, da Mockito.any() ein Object zurückgibt und keiner der überladenen Methoden ein Object als Argument akzeptiert.

Das Verhalten, das Sie mocken, ist also, dass wenn Sie get auf dem WebResource aufrufen, es ein Address-Objekt zurückgeben sollte. Daher sollten Sie Address.class (oder Address im Fall von Groovy, wie Sie es in Ihrem vorherigen Beitrag erwähnt haben) an die get Methode übergeben.

Etwas, das funktionieren sollte (zumindest, wenn ich es mit Java getestet habe), ist beispielsweise:

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("Hallo Welt");

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

Dies sollte "Hallo Welt" ausgeben

4voto

Voicu Punkte 14948

Dies liegt am multiple dispatch Mechanismus in Groovy.

Gießen Sie einfach das Ergebnis des any() Aufrufs in den Typ des überladenen Methodenparameters, den Sie vortäuschen.

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

// das funktioniert auch
when(mockResource.get(any(Address) as Address)).thenReturn(mockAddress)

Imports:

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

Weitere Details auf diese Antwort, diese und diese Blogbeiträge.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X