我在创建模拟Response对象以用于单元测试时遇到问题。我正在使用org.glassfish.jersey.core.jersey-client
版本2.3.1来实现我的RESTful客户端,并使用mockito
版本1.9.5来帮助我处理模拟对象。这是我的测试代码:
@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);
}
执行
this.client.getAll();
时会发生此问题。这是该方法的代码: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;
}
请注意,我使用手动创建的Response模拟了this.simpleClient.getAllWithResponse()方法。当到达
response.readEntity(resourceListType);
指令时,Jersey引发以下异常:java.lang.IllegalStateException - Method not supported on an outbound message.
。经过大量的研究和调试,由于某种原因,当我使用诸如Response.ok(expectedResource, MediaType.APPLICATION_JSON).build();
之类的响应构建器创建一个Response时,它会将其创建为OutboundResponse而不是 InboundResponse 。后者是唯一允许使用Response.readEntity()
方法的方法。如果它是 OutboundResponse ,则抛出异常。但是,我找不到将手动创建的响应转换为InboundResponse的任何方法。所以我的测试注定了:(。你们/加勒斯对我在这里可以做什么有任何想法吗?我不想用Mockito来模拟Response对象,因为我认为这可能是一种代码味道,因为它违反了法律的定律。得墨meter尔(Demeter):真诚的我在这里没有想法,这样的事情应该简单明了。
最佳答案
我遇到此错误是因为当您使用ResponseBuilder
时,它返回了OutboundJaxrsResponse
无法处理的readEntity()
消息。
我注意到只有在直接调用Jax-RS组件时才出现此错误。例如,如果我用DefaultController
注释了@Path("/default")
,并且如果我尝试直接调用其方法,则无法使用readEntity()
并遇到与您相同的错误。
defaultController.get();
现在,当我使用grizzly2测试提供程序并使用客户端将Rest Url作为目标(在以前的示例中,它是
/default
)时,我收到的响应消息是ScopedJaxrsResponse。然后,我可以使用readEntity()
方法。target("/default").request.get();
在您的情况下,您 mock 了simpleClient,以便使用未经jersey处理的
ResponseBuilder
构建的响应进行回复。这相当于直接调用我的DefaultController
方法。在不 mock
readEntity()
方法的情况下,建议您找到一种方法来使Jersey处理您的响应并将其转换为ScopedJaxrsResponse
。希望能有所帮助。