使用模拟响应在 Spring Webflux 中重试单元测试

Unit testing retry in Spring Webflux with mocked response

在单元测试重试期间,模拟的响应似乎被缓存了,或者很可能是我做错了什么。

我正在尝试请求某些东西,如果发生错误,请延迟 1 秒重试两次。

  public Mono<Object> someMethod(String someParam) {
    return someInjectedService.doSomething(someParam)
        .doOnError(ex -> System.out.println(ex + ": " + System.currentTimeMillis()))
        .retryWhen(Retry.fixedDelay(2, Duration.ofSeconds(1)).filter(ex -> ex instanceof SomeCustomException))
        .doOnSuccess(result -> doSomethingOnSuccess(result));
  }

我的测试:

  @Test
  void testshouldRequestThrice_whenErrorOccurs() {
    // Given
    String someParam = "testParam";
    when(someInjectedService.doSomething(someParam))
        .thenReturn(Mono.error(new SomeCustomException("SomeCustomException"))) // 1st response
        .thenReturn(Mono.error(new SomeCustomException("SomeCustomException"))) // 2nd response
        .thenReturn(Mono.just("SomeValidResponse")); // 3rd valid response

    // When
    var result = testService.someMethod(someParam).block();

    // Then
    // Initial request, followed by two retries
    verify(someInjectedService, times(3)).doSomething(someParam);
  }

这里someInjectedService是一个mock。 我的计划是 return 两次异常,第三次请求 return 有效响应。但我得到的是:

org.mockito.exceptions.verification.TooFewActualInvocations: someInjectedService.doSomething("testParam");

Wanted 3 times: -> at shouldRequestThrice_whenErrorOccurs(test.java:138)

But was 1 time:

虽然我确实看到了 .doOnError(ex -> System.out.println(ex + ": " + System.currentTimeMillis())) 块中的 3 个打印件,但我觉得实际请求只发送了一次。

提前谢谢你,

someInjectedService.doSomething(...) 在技术上确实只会被调用一次。

您可以改用 Mono.defer(() -> someInjectedService.doSomething(someParam)),以确保再次有效调用该方法,这应该使您的测试通过。