2

我使用 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。

有什么建议吗?

谢谢 !!

4

2 回答 2

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
}
于 2013-07-12T18:00:37.793 回答
1

其中一些是我的猜测和猜测,但它可能会有所帮助。您可以尝试使用Jersey 测试InMemoryTestContainerFactory框架:

它启动 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...
    }
}

我使用了 inregisterInstances而不是registerClassesin,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...

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

于 2013-07-12T22:43:08.990 回答