Spring reactive WebClient retry tests with StepVerifier

Viewed 675

I have a simple implementation of WebClient request:

public Mono<Todo> getTodoWithSimpleRetry(String id) {
    RetryBackoffSpec retrySpec = Retry.fixedDelay(3, Duration.ofSeconds(2))
            .doBeforeRetry(beforeRetry -> {
                log.info("Attempt to retry: " + (beforeRetry.totalRetries() + 1));
            }).doAfterRetry(afterRetry -> {
                log.error("After retry {}", afterRetry.failure().getMessage());
            })
            .onRetryExhaustedThrow(((retrySpec1, retrySignal) -> {
                throw new TodoServiceException("Max retry exceeded. Todo Service is not available", HttpStatus.SERVICE_UNAVAILABLE.value());
            }));

    return webClient.get()
            .uri("/todo/{id}", id)
            .retrieve()
            .bodyToMono(Todo.class)
            .retryWhen(retrySpec)
            ;
}

and I'm trying to test that exception TodoServiceException will be thrown after all retry attempts but I don't want to wait time between all retries. I found that it could be done through StepVerifier.withVirtualTime. And my example below:

@Test
void testRetry() {
    mockBackEnd.enqueue(new MockResponse().setResponseCode(500));
    mockBackEnd.enqueue(new MockResponse().setResponseCode(500));
    mockBackEnd.enqueue(new MockResponse().setResponseCode(500));
    mockBackEnd.enqueue(new MockResponse().setResponseCode(500));
    
    StepVerifier.withVirtualTime(() -> todoWebClient.getTodoWithSimpleRetry("1"))
            .expectSubscription()
            .thenAwait(Duration.ofSeconds(2))
            .thenAwait(Duration.ofSeconds(2))
            .thenAwait(Duration.ofSeconds(2))
            .expectError(TodoServiceException.class)
            .verify();
}

But the problem is that test always stuck on the second retry and nothing happens.

0 Answers
Related