有没有一种方法可以将verifyNoInteractions与超时结合起来?

5

我有一段 Java 代码,它在 CompletableFuture#runAsync 块中执行,我想验证在这个块中,特定的服务不会被调用。

通常要验证它是否被调用,我可以使用 timeout 验证模式来断言当 runAsync 可能已经完成时。

verify(myService, timeout(500)).methodX(param);

但在我的情况下,我想检查服务是否没有进行任何交互。通常使用verifyNoInteractions(myService);来完成此操作,但这会立即触发并且很容易出现误报。

解决方法是对于服务中的每个方法,我使用times(0) VerificationMode 进行验证。

verify(myService, timeout(500).times(0)).methodX(param);
verify(myService, timeout(500).times(0)).methodY(param);
verify(myService, timeout(500).times(0)).methodZ(param);

出于种种明显的原因,这是一个糟糕的想法。

我知道另一种可能性是添加 Thread.sleep(500);, 但如果可能的话,我希望使用 Mockito API。我只是没有在其他地方看到过这样做。

2个回答

0
非常小心,使用times(0)时要非常小心,因为它的工作方式可能与您期望的不同。 实际上,您可以尝试这段代码,以注意到超时实际上并没有达到,只要第一个有效的Mockito评估通过,verify断言就会通过。
  private static class TestAsync {
    void test() {
      System.out.println("test");
    }
  }

  @Test
  void testAsyncWaitZeroTimes() {

    var testAsync = Mockito.mock(TestAsync.class);
    doCallRealMethod().when(testAsync).test();

    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        testAsync.test();
      }
    }, 1000);

    verify(testAsync, timeout(2000).times(0)).test();

  }

  @Test
  void testAsyncWaitOnce() {

    var testAsync = Mockito.mock(TestAsync.class);
    doCallRealMethod().when(testAsync).test();

    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        testAsync.test();
      }
    }, 1000);

    verify(testAsync, timeout(2000).times(1)).test();

  }

  @Test
  void testAsyncWaitReachingTimeout() {

    var testAsync = Mockito.mock(TestAsync.class);
    doCallRealMethod().when(testAsync).test();

    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        testAsync.test();
      }
    }, 2000);

    verify(testAsync, timeout(1000).times(1)).test();

  }

你会注意到test只在testAsyncWaitOnce测试中被打印出来。
我正在使用一个叫做awaitility的第三方库,它允许我们做一些像这样的事情:
  @Test
  void testAsyncWaitUsingAwaitilityShouldNotBeCalled() {

    var testAsync = Mockito.mock(TestAsync.class);
    doCallRealMethod().when(testAsync).test();

    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        testAsync.test();
      }
    }, 5000);

    await().during(2, TimeUnit.SECONDS)
           .until(() -> Try.run(() -> verify(testAsync, never()).test())
                           .isSuccess());

  }

  @Test
  void testAsyncWaitUsingAwaitilityShouldBeCalledOnce() {

    var testAsync = Mockito.mock(TestAsync.class);
    doCallRealMethod().when(testAsync).test();

    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        testAsync.test();
      }
    }, 1000);

    await().timeout(2, TimeUnit.SECONDS)
           .until(() -> Try.run(() -> verify(testAsync, times(1)).test())
                           .isSuccess());

  }

这样我们就可以看到时间是否正确等待,过去没有发生任何交互。


0
结合超时时间和显示频率
import static org.mockito.Mockito.timeout;

...

verify(spy, timeout(5000).times(1)).doWhatever(comparedArgument);

等待5000毫秒执行doWhatever一次,并检查参数是否等于comparedArgument。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接