用mockito调用Rest方法

时间:2013-07-12 17:44:52

标签: json junit jersey httprequest mockito

我使用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 String。最好的选择是使用mockito。

有关于如何做的建议吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

问题是该方法将Response对象返回给调用者,该调用者深入框架代码中。它不返回JSON字符串。

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

但是你可能需要获取方法返回的值,并将它转换为JSON,如果你使用Jackson和Jersey。

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
}

答案 1 :(得分:1)

其中一些是猜测工作和我的猜测,但它可能会有所帮助。您可以尝试将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...
    }
}

我在registerInstances中使用registerClasses而不是configure(),因为看起来您可以提供现成的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...

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