无法模拟 Glassfish Jersey 客户端响应对象 [英] Unable to Mock Glassfish Jersey Client response object

查看:20
本文介绍了无法模拟 Glassfish Jersey 客户端响应对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在创建用于单元测试的模拟 Response 对象时遇到问题.我正在使用 org.glassfish.jersey.core.jersey-client 版本 2.3.1 来实现我的 RESTful 客户端和 mockito 版本 1.9.5 来帮助我处理模拟对象.这是我的测试代码:

I am having problems with creating a mock Response object to use with my unit tests. I am using org.glassfish.jersey.core.jersey-client version 2.3.1 to implement my RESTful client and mockito version 1.9.5 to help me with mock objects. Here is my test's code:

@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();时出现问题.这是该方法的代码:

The problem occurs when this.client.getAll(); is executed. Here is that method's 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;
}

请注意,我正在使用手动创建的响应来模拟 this.simpleClient.getAllWithResponse() 方法.当它到达 response.readEntity(resourceListType); 指令时,Jersey 会抛出以下异常:java.lang.IllegalStateException - 出站消息不支持方法..经过大量研究和调试后,由于某种原因,当我使用诸如 Response.ok(expectedResource, MediaType.APPLICATION_JSON).build(); 之类的响应构建器创建响应时,它会创建它作为 OutboundResponse 而不是 InboundResponse.后者是唯一允许使用 Response.readEntity() 方法的方法.如果是OutboundResponse,则抛出异常.

Note that I am mocking the this.simpleClient.getAllWithResponse() method with the manually created Response. When it reaches the response.readEntity(resourceListType); instruction, Jersey throws the following exception: java.lang.IllegalStateException - Method not supported on an outbound message.. After lots of research and debugging, it turns that, for some reason, when I create a Response using the response builder such as Response.ok(expectedResource, MediaType.APPLICATION_JSON).build(); it creates it as an OutboundResponse instead of as an InboundResponse. The latter are the only ones permitted to use the Response.readEntity() method. If it is an OutboundResponse, the exception is thrown.

但是,我找不到将手动创建的响应转换为 InboundResponse 的任何方法.所以我的测试注定要失败:(.你们知道我能在这里做什么吗?我不想用 Mockito 模拟 Response 对象,因为我认为它可能是代码味道,因为它违反了法律得墨忒耳.真的,我在这里没有想法.这样的事情应该简单明了.

However, I could not find any way of converting the manually created response to an InboundResponse. So my tests are doomed :(. Do you guys/gals have any idea of what I can do here? I don't want to mock the Response object with Mockito because I think it could be a code smell since it violates the Law of Demeter. Sincerely I am out of ideas here. Things like this should be simple and straightforward.

推荐答案

我遇到这个错误是因为当你使用 ResponseBuilder 时,它返回一个 OutboundJaxrsResponse 消息,无法用 readEntity() 处理.

I had this error because when you use the ResponseBuilder, it returns an OutboundJaxrsResponse message that can not be processed with readEntity().

我注意到只有在直接调用 Jax-RS 组件时才会出现此错误.例如,如果我有 DefaultController@Path("/default") 注释并且如果我试图直接调用它的方法,我不能使用 readEntity() 和你有同样的错误.

I noticed that I had this error only when I was calling the Jax-RS component directly. For exemple, if I have DefaultController annotated with @Path("/default") and if I tried to directly call its method, I could not use readEntity() and had the same error as you.

defaultController.get();

现在,当我使用 grizzly2 测试提供程序并使用客户端来定位 Rest Url(在前一种情况下,它是 /default)时,我收到的响应消息是 ScopedJaxrsResponse.然后我可以使用 readEntity() 方法.

Now, when I was using the grizzly2 test provider and using a client to target the Rest Url (in the previous case, it is /default), the message I received in response was a ScopedJaxrsResponse. And then I could use the readEntity() method.

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

在您的情况下,您模拟了 simpleClient 以便回复使用 ResponseBuilder 构建的响应,该响应未由 jersey 处理.这相当于直接调用我的 DefaultController 方法.

In your case, you mocked the simpleClient in order to reply with a response built with ResponseBuilder that is not processed by jersey. It's comparable to calling directly my DefaultController method.

在不模拟 readEntity() 方法的情况下,我建议您找到一种方法让 Jersey 处理您的响应并转换为 ScopedJaxrsResponse.

Without mocking the readEntity() method, I suggest you to find a way to get your response processed by Jersey and turned into a ScopedJaxrsResponse.

希望对您有所帮助.

这篇关于无法模拟 Glassfish Jersey 客户端响应对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆