Impossible de simuler L'objet de réponse du client De Jersey Glassfish
j'ai des problèmes avec la création d'un objet de réponse simulée à utiliser avec mes tests unitaires. J'utilise la version 2.3.1 de org.glassfish.jersey.core.jersey-client
pour implémenter mon client RESTful et la version 1.9.5 de mockito
pour m'aider avec les objets mock. Voici le code de mon test:
@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);
}
Le problème se produit lorsque this.client.getAll();
est exécuté. Voici le code de cette méthode:
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;
}
notez que je me moque de ceci.simpleClient.méthode getAllWithResponse () avec créés manuellement Réponse. Quand il atteint l'instruction response.readEntity(resourceListType);
, Jersey lance l'exception suivante: java.lang.IllegalStateException - Method not supported on an outbound message.
. Après beaucoup de recherches et de débogage, il s'avère que, pour une raison quelconque, quand je crée une réponse en utilisant le constructeur de réponse tel que Response.ok(expectedResource, MediaType.APPLICATION_JSON).build();
il la crée comme une réponse sortante au lieu d'une réponse entrante . Ces derniers sont les seuls autorisés à utiliser la méthode Response.readEntity()
. Si c'est une réponse , l'exception est lancée.
cependant, je n'ai pu trouver aucun moyen de convertir la réponse créée manuellement à une réponse entrante. Donc mes tests sont condamnés :(. Avez-vous les gars et les filles ont aucune idée de ce que je peux faire ici? Je ne veux pas me moquer de L'objet de réponse avec Mockito parce que je pense que ça pourrait être une odeur de code car ça viole la Loi de Demeter. Sincèrement je suis à court d'idées ici. Ce genre de choses devrait être simple et simple.
6 réponses
j'ai eu cette erreur parce que lorsque vous utilisez le ResponseBuilder
, il renvoie un message OutboundJaxrsResponse
qui ne peut pas être traité avec readEntity()
.
j'ai remarqué que j'avais cette erreur seulement quand j'appelais le composant Jax-RS directement. Par exemple, si j'ai DefaultController
annoté avec @Path("/default")
et si j'ai essayé d'appeler directement sa méthode, Je ne pourrais pas utiliser readEntity()
et avait la même erreur que vous.
defaultController.get();
maintenant, quand je utilisait le fournisseur de test grizzly2 et l'utilisation d'un client pour cibler L'Url Rest (dans le cas précédent, il est /default
), le message que j'ai reçu en réponse était un ScopedJaxrsResponse. Et je pourrais utiliser la méthode readEntity()
.
target("/default").request.get();
dans votre cas, vous vous êtes moqué du simpleClient afin de répondre avec une réponse construite avec ResponseBuilder
qui n'est pas traitée par jersey. C'est comparable à appeler directement ma méthode DefaultController
.
sans vous moquer de la méthode readEntity()
, je vous suggère de trouver un moyen de faire traiter votre réponse par Jersey et de la transformer en un ScopedJaxrsResponse
.
Espère que ça aide.
Plutôt que d'utiliser readEntity(OutputClass.class)
vous pouvez faire quelque chose comme:
OutputClass entity = (OutputClass)outboundJaxrsResponse.entity
vous pouvez aussi vous moquer de la réponse avec 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);
responsabiltatus est le code de statut associé à la réponse et la réponse est bien sûr l'entité que vous voulez retourner. Vous pouvez utiliser cette simulation comme une déclaration de retour dans Mockito (par exemple ... thenReturn(réponse)).
dans mes projets je crée des constructeurs pour différents types de mocassins (dans ce cas réponse), donc je peux facilement sur demande construire des mocassins requis, par exemple réponse avec le code d'état 200 et une entité personnalisée attachée.
pour moi, aucune de ces réponses n'a fonctionné parce que j'essayais d'écrire un test unitaire côté serveur qui testait le corps de l'instance générée Response
, elle-même. J'ai eu cette exception en appelant une ligne comme String entity = readEntity(String.class)
. Au lieu de me moquer de l'objet Response
, je voulais le tester.
la solution pour moi était de substituer la ligne problématique ci-dessus à un comme:
String entity = (String) outboundJaxrsResponse.getEntity();
j'ai résolu en me moquant des réponses:
@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();
ceux-ci peuvent aider si votre direction est de créer manuellement un ScopedJaxrsResponse à la place:
code D'essai:
ClientResponse<?> response = response.getEntity(new GenericType<List<String>>() {});
moquerie:
doReturn("test").when(response).getEntity(any(GenericType.class));