使用Mockito和jUnit为一个方法编写一个单元测试,其中包含两个HTTP调用



我有三种方法,

  • 无效保存(字符串a,字符串b)
  • 字符串getId(字符串a,Pojo p)
  • void update(字符串a、字符串b、字符串实体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*/);
}
}

如前所述,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);

但是在测试时,responsePut返回一个null。参数也匹配。

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

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

谢谢

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

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

HttpResponse response = httpRequestService.makeGetRequest(url, TOKEN_PREFIX, accessToken,
CONTENT_TYPE);

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

when(obj.methodGET(...)).thenReturns(...)

记住:您的单元测试应该而不是通过连线进行调用!

编辑

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);
}

然后:

...
when(mockedStatusLineObj.getStatusCode()).thenReturns(200);
HttpResponse mockedGet = mock(HttpResponse.class);
when(mockedGet.getStatusLine()).thenReturns(mockedStatusLineObj);
when(object.get(...)).thenReturns(mockedGet);
when(object.put(...)).thenReturns(...);

关于测试的方法

事实上,你的测试设置很好,但阅读起来很复杂
测试必须保持可读性和简单性
否则就很难理解和维护它。你想模仿HttpRequestService
如果您想unit-test您的类,而不想考虑集成问题,这是一个很好的方法
但是模拟HttpRequestService的依赖关系的方式使代码不可读:

HttpResponse responsePut = Mockito.mock(HttpResponse.class);
StatusLine statusLinePut = Mockito.mock(StatusLine.class);
Mockito.when(responsePut.getStatusLine()).thenReturn(statusLinePut);
Mockito.when(statusLinePut.getStatusCode()).thenReturn(200);

你在每次调用时都会重复这一点
用一种方法提取:

public HttpResponse createMockedHttpResponse(String url){
HttpResponse responsePut = Mockito.mock(HttpResponse.class);
StatusLine statusLinePut = Mockito.mock(StatusLine.class);
Mockito.when(responsePut.getStatusLine()).thenReturn(statusLinePut);
Mockito.when(statusLinePut.getStatusCode()).thenReturn(200);
return responsePut;
}

关于测试失败

它只是在线路上抛出一个NullPointerException

update()中的if (response.getStatusLine().getStatusCode() == 200)方法

当我调试它时,它显示responsePut为null。

如果我查看您的实际代码,测试中的类中的这些调用:

getStatusLine().getStatusCode()

在这里被正确地嘲笑:

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);

因此,请确保makePutRequest()的记录行为和makePutRequest()的实际调用具有完全相同的/equals()传递参数
如果测试逻辑确实不需要某些参数,请毫不犹豫地通过Mockito.any()

相关内容

  • 没有找到相关文章

最新更新