2013-10-24 9 views
7

Ich habe Probleme beim Erstellen eines Schein-Response-Objekts, das mit meinen Komponententests verwendet werden soll. Ich verwende org.glassfish.jersey.core.jersey-client Version 2.3.1, um meinen RESTful-Client zu implementieren und mockito Version 1.9.5, um mir mit Mock-Objekten zu helfen. Hier ist der Code mein-Test:Kann Glassfish Trikot nicht verwerfen Clientantwortobjekt

@Test 
public void testGetAll() throws IOException { 
    // Given 
    String expectedResource = "expectedResource" 

    final Response expectedRes = Response.ok(expectedResource, MediaType.APPLICATION_JSON).build(); 
    String receivedResource; 

    BDDMockito.given(this.client.getSimpleClient().getAllWithResponse()).willReturn(expectedRes); 

    // When 
    receivedResource = this.client.getAll(); 

    // Then 
    Assert.assertNotNull("Request constructed correctly and response received.", receivedResource); 
    Assert.assertEquals("Resource is equal to expected.", expectedResource, receivedResource); 
} 

Das Problem tritt auf, wenn this.client.getAll(); ausgeführt wird. Hier ist die Methode Code:

public String getAll() throws GenericAragornException, ProcessingException{ 
    Response response = this.simpleClient.getAllWithResponse(); 

    if (response.getStatus() != 200) { 
     processErrorResponse(response); 
    } 

    String entity = response.readEntity(String.class); 

    // No errors so return entity converted to resourceType. 
    return entity; 
} 

Bitte beachte, dass ich spöttisch bin die this.simpleClient.getAllWithResponse() -Methode mit der manuell erstellten Antwort. Wenn es die response.readEntity(resourceListType); Anweisung erreicht, löst Jersey die folgende Ausnahme aus: java.lang.IllegalStateException - Method not supported on an outbound message.. Nach viel Forschung und Debugging, stellt sich, dass aus irgendeinem Grund, wenn ich eine Antwort mit der Antwort Builder erstellen wie Response.ok(expectedResource, MediaType.APPLICATION_JSON).build(); sie es als OutboundResponse statt als InboundResponse schafft. Letztere sind die einzigen, die die Methode Response.readEntity() verwenden dürfen. Wenn es sich um eine OutboundResponse handelt, wird die Ausnahme ausgelöst.

Ich konnte jedoch keine Möglichkeit finden, die manuell erstellte Antwort auf eine InboundResponse zu konvertieren. Also meine Tests sind zum Scheitern verurteilt :(. Weißt du Jungs/Mädels, was ich hier machen kann? Ich möchte das Response - Objekt nicht mit Mockito verspotten, weil ich denke, dass es ein Code - Geruch sein könnte, da es gegen das Gesetz verstößt Demeter. mit freundlichen Grüßen ich aus Ideen bin hier. Dinge wie diese sollte einfach und unkompliziert sein.

Antwort

5

ich diesen Fehler hatte, denn wenn man die ResponseBuilder verwenden, ist es eine OutboundJaxrsResponse Nachricht zurückgibt, die verarbeitet werden können, nicht mit readEntity().

ich bemerkte, dass ich diesen Fehler hatte nur, wenn ich die JAX-RS-Komponente direkt anrief. Für exemple, wenn ich DefaultController mit @Path("/default") kommentiert habe, und wenn ich versuche, direkt seine Methode zu nennen, konnte ich nichtverwendenund hatte den gleichen Fehler wie Sie.

defaultController.get(); 

Nun, wenn ich den grizzly2 Testanbieter wurde mit und einen Client mit dem Ruhe URL Ziel (im vorherigen Fall ist es /default), die Botschaft, die ich als Antwort erhielt, war ein ScopedJaxrsResponse. Und dann könnte ich die readEntity() Methode verwenden.

target("/default").request.get(); 

In Ihrem Fall verspottet Sie die simpleClient, um mit einer Antwort mit ResponseBuilder gebaut, um zu antworten, die nicht von Jersey verarbeitet wird. Es ist vergleichbar mit dem Aufruf meiner DefaultController Methode.

Ohne die readEntity() Methode verspotten, empfehle ich Ihnen, einen Weg zu finden, Ihre Antwort von Jersey verarbeitet und in eine ScopedJaxrsResponse verwandelt.

Hoffe, dass hilft.

+0

Thomas, danke für den Eingang !! Nur eine Frage ... wenn du es wärst ... würdest du die readEntity() -Methode verspotten? –

+0

Es hängt davon ab, was Sie testen möchten? – Thomas

+0

Die getAll-Methode macht das, was sie tun soll, und gibt zurück, was sie zurückgeben soll, je nachdem, was sie empfängt. –

2

Anstatt readEntity(OutputClass.class) verwenden, können Sie etwas tun:

OutputClass entity = (OutputClass)outboundJaxrsResponse.entity 
+0

Nicht ideal, um die Quelle wechseln zu müssen, aber das hat den Trick gemacht. Vielen Dank. –

0

ich die Antworten spöttischen gelöst:

@Spy Response response; 

... 

// for assignments in code under testing: 
doReturn(response).when(dwConnector).getResource(anyString()); 

// for entity and response status reading: 
doReturn("{a:1}".getBytes()).when(response).readEntity(byte[].class); 
doReturn(200).when(response).getStatus(); 

Diese helfen können, wenn Ihr Steer stattdessen eine ScopedJaxrsResponse manuell zu erstellen ist:

1

Sie können auch Mock-Antwort mit Mockito:

final Response response = Mockito.mock(Response.class); 
Mockito.when(response.getStatus()).thenReturn(responseStatus); 
Mockito.when(response.readEntity(Mockito.any(Class.class))).thenReturn(responseEntity); 
Mockito.when(response.readEntity(Mockito.any(GenericType.class))).thenReturn(responseEntity); 

response ist Statuscode mit der Reaktion verbunden und responseEnitty ist natürlich Objekt, das Sie zurückgeben möchten. Sie können diesen Mock als Rückgabeanweisung in Mockito verwenden (z. B. ... thenReturn (Antwort)).

In meinen Projekten erstelle ich Builder für verschiedene Typen für Mocks (in diesem Fall Response), so dass ich auf Anfrage benötigte Mocks, z. Antwort mit Statuscode 200 und einigen angepassten Entitäten.

2

Für mich funktionierte keine dieser Antworten, weil ich versuchte, einen serverseitigen Komponententest zu schreiben, der den Körper der generierten Response Instanz selbst prüfte. Ich habe diese Ausnahme, indem ich eine Zeile wie String entity = readEntity(String.class) anruft. Anstatt zu spotten Response Objekt, wollte ich es testen.

Das Update für mich war es, die oben problematische Linie zu einem wie zu ersetzen:

String entity = (String) outboundJaxrsResponse.getEntity(); 
+0

Oder auch '' 'LinkedHashMap result = (LinkedHashMap) successResponse.getEntity();' '' .. –

+0

Danke, das war hilfreicher als die angenommene Antwort! –