0
我正在爲使用AsyncHttpClient的以下代碼編寫單元測試。在FutureCallback的實現中使用CountDownLatch和遞減CountDownLatch會導致我的JUnit測試用例掛起,等待倒數鎖存器遞減。在JUnit測試中,我使用ArgumentCaptor捕獲FutureCallback,然後使用thenAnswer調用完成的方法來減少向下計數的鎖存器。但它似乎並不奏效,任何想法都將有所幫助。Mockito thenAnswer似乎沒有按預期工作
public List<QueryResponse> execute(Query query) {
List<QueryResponse> res = new ArrayList<QueryResponse>();
try {
List<HttpRequestBase> requests = query.generateHttpRequests();
List<Future<HttpResponse>> futures = new ArrayList<Future<HttpResponse>>();
final CountDownLatch requestCompletionCDLatch = new CountDownLatch(requests.size());
for (HttpRequestBase request : requests) {
futures.add(httpClient.execute(request, new FutureCallback<HttpResponse>() {
@Override
public void failed(Exception e) {
logger.error("Error while executing: " + request.toString(), e);
requestCompletionCDLatch.countDown();
}
@Override
public void completed(HttpResponse result) {
requestCompletionCDLatch.countDown();
}
@Override
public void cancelled() {
logger.info("Request cancelled while executing: " + request.toString());
requestCompletionCDLatch.countDown();
}
}));
}
requestCompletionCDLatch.await();
for (Future<HttpResponse> future : futures) {
HttpResponse response = future.get(rcaRequestTimeout, TimeUnit.SECONDS);
int status = response.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) {
logger.warn("Query with non-success status " + status);
} else {
res.add(query.parseResponse(response.getEntity().getContent()));
}
}
} catch (IOException | InterruptedException | ExecutionException | TimeoutException e) {
logger.error("Error while querying", e);
} catch (URISyntaxException e) {
logger.error("Error while generating the query", e);
}
return res;
}
我的單元測試如下:
@Test
public void testHttpError() throws InterruptedException, ExecutionException, TimeoutException {
StatusLine status = Mockito.mock(StatusLine.class);
when(status.getStatusCode()).thenReturn(400);
HttpResponse response = Mockito.mock(HttpResponse.class);
when(response.getStatusLine()).thenReturn(status);
Future<HttpResponse> future = Mockito.mock(Future.class);
when(future.get(anyLong(), any())).thenReturn(response);
CloseableHttpAsyncClient httpClient = Mockito.mock(CloseableHttpAsyncClient.class);
ArgumentCaptor<HttpUriRequest> requestCaptor = ArgumentCaptor.forClass(HttpUriRequest.class);
ArgumentCaptor<FutureCallback<HttpResponse>> futureCallbackCaptor = ArgumentCaptor.forClass((Class)FutureCallback.class);
when(httpClient.execute(any(), any())).thenReturn(future).thenAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
verify(httpClient).execute(requestCaptor.capture(), futureCallbackCaptor.capture());
futureCallbackCaptor.getValue().completed(response);
return null;
}
});
StubbedRcaClient rcaClient = new StubbedRcaClient(httpClient);
Query query = new Query("abc", "xyz", RcaHttpRequestType.GET, 1000);
List<QueryResponse> res = rcaClient.execute(query);
assertEquals(0, res.size());
IOUtils.closeQuietly(rcaClient);
}
這個測試是非常複雜的,包括用於檢驗邏輯答案。也許你可以重構它,讓社區和維護程序員更容易理解?例如,查看https://dzone.com/refcardz/mockito等單元測試的一些示例。有一個清晰的結構給出/何時/那麼。在使單元測試按預期工作方面,什麼是「StubbedRcaClient」,它是否正確地委託給'httpClient'?另外,不要模擬'Future' - 你不知道回調是使用'get(long,TimeUnit)'還是'Future'裏面的另一個方法' –
我試圖模擬來自HttpAsyncClient的響應,如果我不'嘲笑未來你有什麼建議? – KunalC
https://stackoverflow.com/questions/13866533/how-to-create-a-completed-future-in-java –