Java 在使用Mockito的JUnit中,如何等待异步方法完成?

Java 在使用Mockito的JUnit中,如何等待异步方法完成?,java,asynchronous,mockito,integration-testing,spy,Java,Asynchronous,Mockito,Integration Testing,Spy,我正在针对一些代码编写一个集成测试,这些代码在数据库中更新不同的值时异步创建一个记录。我想在记录创建后检查系统的状态,验证它是否按预期创建。因此,测试需要等待,直到创建记录 我可以使用Mockito为创建记录的函数创建一个间谍。Mockito甚至可以选择通过Mockito.timeout等待调用该方法,如果经过一定时间而没有调用该方法,则放弃: // Use or create/wire in spy. In my case, this is set up with @SpyBean from

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

我可以使用Mockito为创建记录的函数创建一个间谍。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中并不直接存在,因为将此功能添加到Mockito()中目前存在一个未决问题

我目前使用的解决方案是为spied方法编写一个自定义答案,等待调用完成后再返回。之后,我会正常验证结果

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

此功能不直接存在于Mockito中,因为将此功能添加到Mockito()中目前存在一个未决问题

我目前使用的解决方案是为spied方法编写一个自定义答案,等待调用完成后再返回。之后,我会正常验证结果

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

该方法是否有可能返回一个
未来的
?@chrylis onstrike-不太可能,因为它是一个非常正交的功能。在这个特定的实例中,我有一个侦听器侦听数据库中的更改,并根据更改创建审计记录。因此,进行更新的方法对正在创建的审核记录没有直接的了解。该方法是否可能返回一个
未来的
?@chrylis onstrike-不太可能,因为它是一个非常正交的功能。在这个特定的实例中,我有一个侦听器侦听数据库中的更改,并根据更改创建审计记录。因此,进行更新的方法并不直接知道正在创建的审计记录。