CompletableFuture.runAsync()的Mockito测试用例,它调用无效方法

时间:2019-03-28 06:13:57

标签: java spring-boot junit java-8 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()是无效方法。

在下面尝试过,但是没有用

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

    }

2 个答案:

答案 0 :(得分:1)

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

您会遇到getCouponAndNotifyAsync()getCouponAndNotify()返回之间的竞争情况。有一些解决方案:

由于您使用的是普通ForkJoinPool,所以

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

It waits for the task to finish

或者,您可以注入ExecutorService并将其用作supplyAsync()的第二个参数。您有几种选择:可以使用模拟,可以使用runs with the current threadExecutorService,也可以注入标准的Executors.newSingleThreadExecutor(),然后调用shutdown()和{{ 1}}。

您还可以从awaitTermination()返回一个CompletionStage<Void>,以便在测试中等待。

答案 1 :(得分:0)

假设您有以下代码:

public void method() {
        CompletableFuture.runAsync(() -> {
            //logic
            //logic
            //logic
            //logic
        });
    }

尝试将其重构为如下形式:

public void refactoredMethod() {
    CompletableFuture.runAsync(this::subMethod);
}

private void subMethod() {
    //logic
    //logic
    //logic
    //logic
}

然后,以这种方式测试subMethod:

org.powermock.reflect.Whitebox.invokeMethod(classInstance, "subMethod"); 
Mockito.verify(...)

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