使用 Mockito 和 jUnit 为具有两个 HTTP 调用的方法编写单元测试

Aki*_*ghe 5 java junit unit-testing mocking mockito

我有三种方法,

  • 无效保存(字符串a,字符串b)
  • String getId(String a, Pojo p)
  • 无效更新(字符串a,字符串b,StringEntity c)

这是实现(不是完整的实现),

String getId(String accessToken, Pojo p) {

    //Note that the pojo is for formatting the payload for the request, nothing more

    HttpResponse response = httpRequestService.makeGetRequest(url, TOKEN_PREFIX, accessToken,
            CONTENT_TYPE);
    if (response.getStatusLine().getStatusCode() == 200) {
        log.debug("Success");
    }

    //Code for getting the id from the response

    return id;
}

void update(String accassToken, String id, StringEntity payload) {

    HttpResponse response = httpRequestService.makePutRequest(url + id,
            TOKEN_PREFIX, accessToken, CONTENT_TYPE, payload);

    if (response.getStatusLine().getStatusCode() == 200) {
        log.debug("Success");
    }
}

void save(String accessToken, String payload) {

    //The getId() is called here
    String id = getId(/*arguments*/);

    if(id == null) {
        log.error("Error");
    } else {
        //The update() is called here
        update(/*arguments*/);
    }
}
Run Code Online (Sandbox Code Playgroud)

如前所述,getId 和 update 方法在 save 方法内部调用,并且 getId 和 update 方法都有 HTTP 调用。

我必须为 save() 方法编写一个单元测试。这就是我尝试过的。

    //This is an interface with methods to call HTTP requests.
    HttpRequestService httpRequestService = Mockito.mock(HttpRequestService.class);

    //Constructor injection
    ClassWithMethods a = new ClasswithMethods(httpRequestService);

    HttpResponse responseGet = Mockito.mock(HttpResponse.class);
    StatusLine statusLineGet = Mockito.mock(StatusLine.class);
    HttpEntity httpEntity = Mockito.mock(HttpEntity.class);
    Mockito.when(responseGet.getStatusLine()).thenReturn(statusLineGet);
    Mockito.when(statusLineGet.getStatusCode()).thenReturn(200);
    Mockito.when(responseGet.getEntity()).thenReturn(httpEntity);
    Mockito.when(httpEntity.getContent()).thenReturn(IOUtils.toInputStream(stream));
    Mockito.when(httpRequestService.makeGetRequest(url, TOKEN_PREFIX, accessToken,
            CONTENT_TYPE).thenReturn(responseGet);

    HttpResponse responsePut = Mockito.mock(HttpResponse.class);
    StatusLine statusLinePut = Mockito.mock(StatusLine.class);
    Mockito.when(responsePut.getStatusLine()).thenReturn(statusLinePut);
    Mockito.when(statusLinePut.getStatusCode()).thenReturn(200);
    Mockito.when(httpRequestService.makePutRequest(url + id, TOKEN_PREFIX,
            accessToken, CONTENT_TYPE, payloadEntity).thenReturn(responsePut);

    a.save(accessToken, payload);
Run Code Online (Sandbox Code Playgroud)

但测试时,responsePut 返回 null。论据也相匹配。

问题:如何测试调用两个 HTTP 方法的保存方法?

这可能不是最好的方法。如果有更好的方法来测试这样的方法,请提出建议。

谢谢

请注意,httpRequestService 是一个带有 HTTP 调用方法的接口,并且也使用构造函数注入。

alf*_*sin 3

您应该将以下内容提取到一个单独的方法中(PUT 也是如此):

HttpResponse response = httpRequestService.makeGetRequest(url, TOKEN_PREFIX, accessToken,
            CONTENT_TYPE);
Run Code Online (Sandbox Code Playgroud)

然后你可以使用mockito 来存根该方法:

when(obj.methodGET(...)).thenReturns(...)
Run Code Online (Sandbox Code Playgroud)

请记住:您的单元测试不应通过网络进行调用!

编辑

private HttpResponse get(String url, ...) {
    return httpRequestService.makeGetRequest(url, TOKEN_PREFIX, accessToken,
            CONTENT_TYPE);
}


private HttpResponse put(String url, ...) {
    return httpRequestService.makePutRequest(url + id,
        TOKEN_PREFIX, accessToken, CONTENT_TYPE, payload);
}
Run Code Online (Sandbox Code Playgroud)

进而:

...
when(mockedStatusLineObj.getStatusCode()).thenReturns(200);
HttpResponse mockedGet = mock(HttpResponse.class);
when(mockedGet.getStatusLine()).thenReturns(mockedStatusLineObj);
when(object.get(...)).thenReturns(mockedGet);
when(object.put(...)).thenReturns(...);
Run Code Online (Sandbox Code Playgroud)