[英]Writing a unit test for a method with two HTTP calls with Mockito and jUnit
我有三種方法,
以下是實現(不是完整的實現),
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方法的save方法?
這可能不是最好的方法。 如果有更好的方法來測試這樣的方法,請建議。
謝謝
請注意,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()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.