java - 在带有 Mockito 的 JUnit 中,如何等待异步方法完成?

标签 java asynchronous mockito integration-testing spy

我正在针对一些代码编写集成测试,当数据库中更新不同的值时,这些代码会异步创建记录。我想在创建记录后检查系统的状态,验证它是否按预期创建。因此测试需要等待记录创建。

我可以使用 Mockito 为创建记录的函数创建一个 spy 。 Mockito 甚至可以选择通过 Mockito.timeout 等待方法被调用,如果经过一定时间而没有调用该方法则放弃:

// Use or create/wire in spy. In my case, this is set up with @SpyBean from spring-boot-test.
RecordCreationService recordCreationServiceSpy = ...;

testClass.update(someValue);

Mockito.verify(recordCreationServiceSpy, Mockito.timeout(10_000)).createRecord(ArgumentMatchers.any());

但是,这只是等待调用开始,而不是等待调用完成。因此,这会进入竞争条件,验证可以在所需的调用完成之前完成。

在使用 Mockito 在 JUnit 中进行验证之前,如何干净、简单地等待流程完成?

最佳答案

此功能并不直接存在于 Mockito 中,因为当前存在一个 Unresolved 问题,无法将此功能添加到 Mockito ( Mockito issue #1089 )。

我当前使用的解决方案是为监视方法编写一个自定义答案,该方法等待调用完成后再返回。然后我就正常验证结果了。

@SpyBean
private RecordCreationService recordCreationServiceSpy;

@Test(timeout = 10_000)
public void recordShouldBeCreatedWhenDataIsUpdated() {
    // Set up test here

    updateValueAndWait(value);

    assertEquals(1, recordRepository.findAll().size());
    // Perform any additional verifications
}

private void updateValueAndWait(String value) {
    CountDownLatch latch = new CountDownLatch(1);
    Mockito.doAnswer(invocation -> {
        Object result = invocation.callRealMethod();
        latch.countDown();
        return result;
    }).when(recordCreationServiceSpy).insertRecord(any());

    testClass.update(value);

    try {
        latch.await();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

关于java - 在带有 Mockito 的 JUnit 中,如何等待异步方法完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59496947/

相关文章:

Java构造函数奇怪的行为

java - 按类名运行程序

javascript - 当外部 JavaScript 完成时得到提醒

java - 使用 Mockito 测试 j.u.f.Supplier 的惰性初始化

java - 使用 opencv 的 Android 文档扫描仪

java - 没有名为 EntityManager 的持久性提供程序

java - 如何用Java实现异步应用程序

c# - 如何阻塞一个线程,直到另一个线程在 C# 中获得服务器响应

unit-testing - 为什么 Mockito "when"在非模拟对象上工作?

java - JMockit 相当于 whenNew