Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactor StepVerifier.withVirtualTime blocks indefinitely

I'm trying to use Reactor's virtual time feature, but the test blocks indefinitely (without timeout) or throws an AssertionError (with timeout):

@Test
public void test() {
    StepVerifier.withVirtualTime(() -> 
            Flux.just(1, 2, 3, 4).delayElements(Duration.ofSeconds(1)))
            .expectSubscription()
            .expectNextCount(4)
            .expectComplete()
            .verify(Duration.ofSeconds(10));
}

The exception is:

java.lang.AssertionError: VerifySubscribertimed out on reactor.core.publisher.FluxConcatMap$ConcatMapImmediate@66d1af89

The same example with real time works as expected:

@Test
public void test2() {
    StepVerifier.create(Flux.just(1, 2, 3, 4).delayElements(Duration.ofSeconds(1)))
            .expectSubscription()
            .expectNextCount(4)
            .expectComplete()
            .verify(Duration.ofSeconds(10));
}

I can not see an error in my first example following Manipulating Time from the reference.

What is wrong?

like image 551
deamon Avatar asked Dec 23 '22 14:12

deamon


1 Answers

You need to use .thenAwait(Duration), otherwise the (virtual) clock won't move, and the delay never happens. You can also use .expectNoEvent(Duration) after the expectSubscription().

For example:

@Test
public void test() {
  StepVerifier.withVirtualTime(() -> 
        Flux.just(1, 2, 3, 4).delayElements(Duration.ofSeconds(1)))
        .expectSubscription() //t == 0
//move the clock forward by 1s, and check nothing is emitted in the meantime
        .expectNoEvent(Duration.ofSeconds(1))
//so this effectively verifies the first value is delayed by 1s:
        .expectNext(1)
//and so on...
        .expectNoEvent(Duration.ofSeconds(1))
        .expectNext(2)
//or move the clock forward by 2s, allowing events to take place,
//and check last 2 values where delayed
        .thenAwait(Duration.ofSeconds(2))
        .expectNext(3, 4)
        .expectComplete()
//trigger the verification and check that in realtime it ran in under 200ms
        .verify(Duration.ofMillis(200));
}
like image 111
Simon Baslé Avatar answered Jan 14 '23 19:01

Simon Baslé