我需要帮助为下面的方法编写模拟测试用例。
public void getCouponAndNotifyAsync(String countryId, String channelId,
String storeNumber, String clientId, NotificationRequest notificationRequest)
throws FirestoreException, TurneroServiceException {
CompletableFuture.runAsync(() -> getCouponAndNotify(countryId, channelId,
storeNumber, clientId, notificationRequest));
}
其中 getCouponAndNotify(( 是一个 void 方法。
在下面尝试过,但它不起作用
@Test
public void getCouponAndNotifyAsync() throws Exception {
//doNothing().when(turneroService).getCouponAndNotify(COUNTRYID, CHANNELID, STORENUMBER, CLIENTID, new NotificationRequest("ext_rborse@falabella.cl", "all"));
CompletableFuture<Void> runAsync = CompletableFuture
.runAsync(() -> doNothing().when(turneroService).getCouponAndNotify(COUNTRYID, CHANNELID, STORENUMBER, CLIENTID, new NotificationRequest("ext_rborse@falabella.cl", "all")));
assertTrue(runAsync.isDone());
}
更新了测试用例,但仍然无法正常工作。
@Test
public void getCouponAndNotifyAsync() throws Exception {
//doNothing().when(turneroService).getCouponAndNotify(COUNTRYID, CHANNELID, STORENUMBER, CLIENTID, new NotificationRequest("ext_rborse@falabella.cl", "all"));
CompletableFuture<Void> runAsync = CompletableFuture
.runAsync(() -> doNothing().when(turneroService).getCouponAndNotify(COUNTRYID, CHANNELID, STORENUMBER, CLIENTID, new NotificationRequest("ext_rborse@falabella.cl", "all")));
assertTrue(ForkJoinPool.commonPool().awaitQuiescence(5, TimeUnit.SECONDS));
assertTrue(runAsync.isDone());
}
我假设您正在其他地方测试getCouponAndNotify()
,因此您不必担心它会引发异常。
您将遇到的是getCouponAndNotifyAsync()
和getCouponAndNotify()
返回之间的竞争条件。对此有几种解决方案:
由于您使用的是通用ForkJoinPool
,因此请执行
assertTrue(ForkJoinPool.commonPool().awaitQuiescence(5, TimeUnit.Seconds));
它等待任务完成。
或者,您可以注入一个ExecutorService
并将其用作supplyAsync()
的第二个参数。您有几种选择:可以使用模拟,可以使用与当前线程一起运行的ExecutorService
,也可以注入标准Executors.newSingleThreadExecutor()
,然后在测试中调用shutdown()
和awaitTermination()
。
您还可以从getCouponAndNotifyAsync()
返回可在测试中等待的CompletionStage<Void>
。
假设你有以下代码:
public void method() {
CompletableFuture.runAsync(() -> {
//logic
//logic
//logic
//logic
});
}
尝试将其重构为如下所示的内容:
public void refactoredMethod() {
CompletableFuture.runAsync(this::subMethod);
}
private void subMethod() {
//logic
//logic
//logic
//logic
}
之后,以这种方式测试子方法:
org.powermock.reflect.Whitebox.invokeMethod(classInstance, "subMethod");
Mockito.verify(...)
这不是一个完美的解决方案,但它测试了异步执行中的所有逻辑。
若要验证异步方法是否已调用,可以使用
verify(<<your service>>, **timeout(100)**.times(1))
.<<your method>>(<< arguments>>);
前任:-
verify(service, **timeout(100)**.times(1))
.getCouponAndNotify(anyString(), anyString(), anyString(), anyString(), any(NotificationRequest.class));
请参阅 https://www.javadoc.io/doc/org.mockito/mockito-core/2.2.9/org/mockito/verification/VerificationWithTimeout.html