JUnit 使用 CompletableFuture.supplyAsync 测试方法调用

问题描述 投票:0回答:1

在我的类中,我有一个类字段,我正在验证该类字段的方法被调用三次。现在我将逻辑移至“CompletableFuture.sypplyAsync”方法,它不再起作用: 我的测试失败了,它说它不会被调用,这正是我所期望的。

我的班级:

import org.camunda.bpm.engine.RuntimeService; 

public class StartProcessService {
    private final RuntimeService runtimeService;
   
    public void handleInExkassodatenRequest(MyRequest request) {
        request.getDaten().forEach(entity -> {
            CompletableFuture.supplyAsync(() -> selectRequiredProcess(entity))
                    .thenAccept(caseId -> {
                        log.info("Case started ");
                    })
                    .exceptionally(err -> {
                        return null;
                    });
        });
    }

    private CompletableFuture<String> selectRequiredProcess(InExkassodaten entity) {
        startNewProcess(entity);
        return CompletableFuture.completedFuture(entity.getCaseId());
    }

    private void startNewProcess(MyObject myObject) {
        ProcessInstance processInstance = runtimeService
                .createProcessInstanceByKey("MY_KEY")
                .setVariable("MY_VAR", myObject)
                .execute();
    }
}

我的旧测试方法如下所示:

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class MyServiceTest {

    @InjectMocks
    private StartProcessService startProcessService;

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private RuntimeService runtimeService;


        @Test
void startProcesses() {

    ProcessInstantiationBuilder processInstanceByKey = mock(ProcessInstantiationBuilderImpl.class);
    when(runtimeService.createProcessInstanceByKey(anyString())).thenReturn(processInstanceByKey);
    when(processInstanceByKey.setVariable(anyString(), any())).thenReturn(processInstanceByKey);
    when(processInstanceByKey.execute()).thenReturn(mock(ProcessInstance.class));

    startProcessService.handleInExkassodatenRequest(InExkassodatenFactory.createValidTestData());
    verify(runtimeService, times(3)).createProcessInstanceByKey(anyString());
}

之前检查了是否调用了runtimeService.createProcessInstanceByKey。 但是随着 CompletableFutur.supplyAsync 的引入失败,并进入“异常”错误:

需要但未调用:runtimeService.createProcessInstanceByKey( ); -> 在 实际上,与这个mock.StartProcessServiceTest.startProcesses(StartProcessServiceTest.java:52)的交互为零

我需要如何重新设计我的生产代码或测试代码才能使用 CompleableFuture 进行测试?

mockito junit5 completable-future camunda
1个回答
0
投票

supplyAsync
正如其名称所示:它异步运行代码。它不保证代码块将在when被执行。

我看到两个明显的修复:

  1. supplyAsync
    采用可选的
    Executor
    参数。默认是在
    ForkJoinPool.commonPool
    上执行,但您可以传递任何其他执行器。一种可能的执行器值是
    Runnable::run
    ,它将直接执行代码,而不将其分派到线程池(因此代码保持单线程)。您可以扩展您的类以拥有执行程序字段或属性,并在测试中将
    Runnable::run
    分配给该字段。

  2. 使用

    Awaitility
    重新运行断言,直到达到给定超时。类似于
    await().untilAsserted(() -> verify(yourMock, times(3)).yourCall())

我建议第一种方法,因为它消除了多线程的复杂性并使事情变得简单。

© www.soinside.com 2019 - 2024. All rights reserved.