Java 调用void方法的CompletableFuture.runAsync()的Mockito测试用例

Java 调用void方法的CompletableFuture.runAsync()的Mockito测试用例,java,spring-boot,junit,java-8,mockito,Java,Spring Boot,Junit,Java 8,Mockito,我需要帮助为下面的方法编写mockito测试用例 public void getCouponAndNotifyAsync(String countryId, String channelId, String storeNumber, String clientId, NotificationRequest notificationRequest) throws FirestoreException, TurneroServiceException { Co

我需要帮助为下面的方法编写mockito测试用例

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

    }
@测试
public void getCouponAndNotifyAsync()引发异常{
//doNothing().when(TurnerService).getCouponAndNotify(COUNTRYID、CHANNELID、STORENUMBER、CLIENTID、new NotificationRequest(“ext_rborse@falabella.cl“,”全部“);
CompletableFuture运行异步=CompletableFuture
.runAsync(()->doNothing().when(TurnerService).getCouponAndNotify(COUNTRYID、CHANNELID、STORENUMBER、CLIENTID、new NotificationRequest(“ext_rborse@falabella.cl","全部";;
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());

    }
@测试
public void getCouponAndNotifyAsync()引发异常{
//doNothing().when(TurnerService).getCouponAndNotify(COUNTRYID、CHANNELID、STORENUMBER、CLIENTID、new NotificationRequest(“ext_rborse@falabella.cl“,”全部“);
CompletableFuture运行异步=CompletableFuture
.runAsync(()->doNothing().when(TurnerService).getCouponAndNotify(COUNTRYID、CHANNELID、STORENUMBER、CLIENTID、new NotificationRequest(“ext_rborse@falabella.cl","全部";;
assertTrue(ForkJoinPool.commonPool().waitquisition(5,TimeUnit.SECONDS));
assertTrue(runAsync.isDone());
}

我假设您正在其他地方测试
getCouponAndNotify()
,所以您不必担心它会引发异常

您将遇到
getCouponAndNotifyAsync()
getCouponAndNotify()
之间的竞争条件。有几种解决方案:

由于您使用的是公共
ForkJoinPool
,请执行以下操作:

assertTrue(ForkJoinPool.commonPool().awaitQuiescence(5, TimeUnit.Seconds));

或者,您可以插入一个
ExecutorService
,并将其用作
supplyAsync()
的第二个参数。您有几个选择:您可以使用一个模拟,您可以使用一个
ExecutorService
,或者您可以插入一个标准的
Executors.newSingleThreadExecutor()
,然后在测试中调用
shutdown()
waittermination()


您还可以从
getCouponAndNotifyAsync()
返回一个
CompletionStage
,您可以在测试中等待它。

假设您有以下代码:

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(...)

这不是一个完美的解决方案,但它测试了异步执行中的所有逻辑。

在我的测试用例中assertTrue之前编写的任何内容都可以吗?更新了相关的测试用例,但仍然不起作用。是否尝试使用?您最好在测试中扩展类并重写同步方法。您在测试中在哪里调用
getCouponAndNotifyAsync()
?我也不认为模仿像你想象的那样有效。你能解释一下吗?正在控制器类中调用getCouponAndNotifyAsync()。那项测试通过了。