如何测试需要外部休息呼叫的方法?

时间:2017-03-26 06:43:32

标签: java unit-testing junit mocking mockito

我想对通过外部访问管理基础架构登录用户的方法进行单元测试。我不知道如何模仿Response response对象。

这是我打算测试的代码:

public String login(final String username, final String password) {
    String baseUrl = getOpenAMApiBaseUrl();
    String path = "/openam/json/authenticate";

    // Response NEEDS TO BE MOCKED SOMEHOW
    Response response = jaxClient.target(baseUrl + path)
            .request(MediaType.APPLICATION_JSON_TYPE)
            .header(HttpHeaderField.OPENAM_USERNAME, username)
            .header(HttpHeaderField.OPENAM_PASSWORD, password)
            .post(Entity.json(null));

    int status = response.getStatus();
    String jsonResponse = response.readEntity(String.class);

    if (status == Response.Status.OK.getStatusCode()) {
        try (JsonReader jsonReader = Json.createReader(new StringReader(jsonResponse))) {
            JsonObject jsonObject = jsonReader.readObject();
            String token = jsonObject.getString("tokenId");
            LOGGER.info("{} have successfully logged in", username);
            return token;
        } catch (NullPointerException e) {
            LOGGER.info("login failed, invalid json response for {}/{}", username, password);
            return null;
        }
    }

    String message = "an error occurred during logging in, http status: {}, user: {}/{}";
    if (status == Response.Status.UNAUTHORIZED.getStatusCode()) {
        message = "invalid credentials, http status: {}, user: {}/{}";
    }
    LOGGER.info(message, status, username, password);
    return null;
}

1 个答案:

答案 0 :(得分:2)

理想情况下,您必须从jaxClient.target方法开始模拟所有调用,但在这种情况下,由于生成模拟需要非常长的链,我建议使用以下两个选项之一:

1)(首选) - 将响应的创建提取到仅专门用于该特定操作的新类。

然后你会声明该类作为被测试类的依赖关系,只需使用配置为返回某个Response对象的构建器方法注入它的模拟。

2)您可以在类中创建一个包级别方法,如下所示:

Response buildResponse(){
    String baseUrl = getOpenAMApiBaseUrl();
    String path = "/openam/json/authenticate";

    // Response NEEDS TO BE MOCKED SOMEHOW
    Response response = jaxClient.target(baseUrl + path)
            .request(MediaType.APPLICATION_JSON_TYPE)
            .header(HttpHeaderField.OPENAM_USERNAME, username)
            .header(HttpHeaderField.OPENAM_PASSWORD, password)
            .post(Entity.json(null));
}

然后@Spy您正在测试的类并模拟该方法以返回您想要的响应:

@Spy
ClassUnderTest classUnderTest;

@Mock
Response responseMock;

@Before
public void init(){
    MockitoAnnotations.initMocks(this);
}

@Test
public void test(){
    doReturn(responseMock).when(classUnderTest).buildResponse();

    // Act

    classUnderTest.login(login,pass);

   // Assertions
}