【问题标题】:Call a Rest method with mockito使用 mockito 调用 Rest 方法
【发布时间】:2013-07-12 17:44:51
【问题描述】:

我使用 Jersey,并且我有以下 Rest 函数,它在部署我的服务器时返回一个 JSON 字符串:

@GET
@Path("getallemployees")
@Produces("application/json")
public Response getAllEmployees() {
//building the entity object which is List<Employee>
return Response.ok(entity).build();
}

我需要开发一些单元测试(不是集成测试),我想以某种方式模拟调用此方法的 HTTPRequest,然后获取 json 字符串。最好的选择是为此使用 mockito。

有什么建议吗?

谢谢!!

【问题讨论】:

    标签: json junit jersey httprequest mockito


    【解决方案1】:

    问题在于该方法返回一个Response 对象给调用者,该对象位于框架代码的深处。它不返回 JSON 字符串。

    如果您需要在方法本身内部模拟某些内容,您可以使用 Mockito。应该可以的。

    但如果您将 Jackson 与 Jersey 一起使用,您可能需要获取该方法返回的值并将其转换为 JSON。

    Response response = getAllEmployees();
    Object retval = response.getEntity();
    try {
        ObjectMapper mapper = new ObjectMapper();
        // I like this formatting. You can change it.
        mapper.configure(Feature.INDENT_OUTPUT, true);
        mapper.configure(Feature.WRITE_ENUMS_USING_TO_STRING, true);
        mapper.configure(Feature.USE_ANNOTATIONS, false);
        mapper.configure(Feature.FAIL_ON_EMPTY_BEANS, false);
        mapper.setSerializationInclusion(Inclusion.NON_NULL);
        mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
        mapper.getSerializationConfig().withSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
        String json = mapper.writeValueAsString(retval);
        ... assert something about the string
    } catch (JsonProcessingException e) {
        // do something
    } catch (IOException e) {
        // do something
    }
    

    【讨论】:

    • 您使用哪个 Jackson 版本?因为无法识别 Feature.INDENT_OUTPUT ...
    • 好吧,这确实有效:),唯一的问题是我将整个实体对象作为 JSON 字符串获取,它看起来像这样:{"rawType":"java.util.ArrayList","type":{"actualTypeArguments":["dev.entities.Employee"],"rawType":"java.util.List"},"entity":[{"idEmployee":0,"name":"theName","surname":"theSurname"} 而原始 json 看起来像这样:"employee":[{"idEmployee":0,"name":"theName","surname":"theSurname"}
    • 对不起。您必须先将实体从响应中取出。更改了代码示例来做到这一点。我不完全确定会做对,但类似的事情。
    • 实际上,我在之前的评论中打印的消息是我从响应中删除实体得到的消息。它不是json字符串,但几乎是一样的......
    • 它似乎在里面。必须是其他东西才能得到原始结果。
    【解决方案2】:

    其中一些是我的猜测和推测,但它可能会有所帮助。您可以尝试将Jersey Test FrameworkInMemoryTestContainerFactory 一起使用:

    它启动 Jersey 应用程序并直接调用内部 API 来处理由测试框架提供的客户端创建的请求。不涉及网络通信。此容器不支持 servlet 和其他容器相关功能,但它是简单单元测试的完美选择。

    它看起来像使用它,您需要做的就是扩展JerseyTest,然后覆盖getTestContainerFactory()并按照其余说明进行操作,例如:

    public class EmployeeResourceTest extends JerseyTest {
        @Override
        protected Application configure() {
            // set up employee resource with mock dependencies etc...
            return new ResourceConfig().registerInstances(employeeResource);
        }
    
        @Test
        public void getAllEmployees() {
            final String response = target("getallemployees").request().get(String.class);
            // assert etc...
        }
    }
    

    我在configure() 中使用了registerInstances 而不是registerClasses,因为看起来您可以提供现成的Resource,但可以设置您可能想要的任何模拟依赖项——尽管我自己没有尝试过。

    测试类有点不灵活,因为您只能在 configure() 方法中一次性设置依赖项,因此使用 MockitoJUnitRunner 可能值得研究 - 尽管我不确定它是否会使用JerseyTest 继承。它可以让您在每个 @Test 方法中为模拟添加行为,例如:

        @Mock
        private EmployeeResourceDependency dependency;
    
        @InjectMocks
        private EmployeeResource employeeResource;
    
        // configure() as above but without mock setup up etc...
    
        @Test
        public void getAllEmployees() {
            given(dependency.getEmployees()).willReturn(...); 
    
            // etc...
    

    但就像我说的那样,可能根本无法混合它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-02
      • 2017-06-03
      • 2017-01-17
      • 1970-01-01
      相关资源
      最近更新 更多