【问题标题】:In JUnit with Mockito, how can I wait for an asynchronous method to complete?在带有 Mockito 的 JUnit 中,如何等待异步方法完成?
【发布时间】:2020-04-17 04:47:18
【问题描述】:

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

我可以使用 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 中进行验证之前,我如何才能干净而简单地等待流程完成?

【问题讨论】:

  • 该方法是否可以返回Future
  • @chrylis-onstrike- 不是真的,因为它是一个相当正交的功能。在这个特定的例子中,我有一个监听器监听数据库中的变化,并根据变化创建一个审计记录。因此,进行更新的方法不直接了解正在创建的审计记录。

标签: java asynchronous mockito integration-testing spy


【解决方案1】:

此功能在 Mockito 中不直接存在,因为当前存在一个未解决的问题,可将此功能添加到 Mockito (Mockito issue #1089)。

我目前使用的解决方案是为 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);
    }
}

【讨论】:

    猜你喜欢
    • 2013-02-15
    • 1970-01-01
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    • 2014-08-09
    相关资源
    最近更新 更多