reactor / reactor-core

Non-Blocking Reactive Foundation for the JVM
http://projectreactor.io
Apache License 2.0
4.96k stars 1.2k forks source link

expectNoEvent does not fail on emission #3331

Open stefnoten-aca opened 1 year ago

stefnoten-aca commented 1 year ago

Expected Behavior

expectNoEvent fails when a emission happens

Actual Behavior

expectNoEvent does not fail on an emission

Steps to Reproduce

@Test
void shouldFailButDoesNot() {
    StepVerifier.withVirtualTime(() -> Flux.never().startWith("a"))
                .expectSubscription()
                .expectNoEvent(Duration.ofSeconds(1)) // should fail
                .expectNext("a")
                .verifyTimeout(Duration.ofSeconds(1));
}

Also incorrectly succeeds:

Your Environment

OlegDokuka commented 1 year ago

@stefnoten-aca Thanks for finding that!

Unfortunately, no promises of a fix 😔. The issue is related to the StepVerifier design and what you observe could be a design flaw.

The problem is that expectNoEven triggers VirtualTimeScheduler to progress by 1 second. Since the startWith has nothing to do with schedulers, the progress will basically do nothing, hence no events will be produced during the expectNoEvents stage. Unfortunately, we don't have a mechanism to put the expectNoEvents stage back in the queue and wait for another event and check whether the event arrived during expectation or not.

All that said - try to redesign your test and use a different approach to verify event time.

One possible workaround could be the use of elapsed operator in combination with predictable virtual time

@Test
    void shouldFailButDoesNot() {
        StepVerifier.withVirtualTime(() -> Flux.never().startWith("a").elapsed())
                    .expectSubscription()
                    .expectNoEvent(Duration.ofSeconds(1)) // should fail
                    .expectNextMatches(e -> e.getT2().equals("a") && e.getT1() >= 1000)
                    .verifyTimeout(Duration.ofSeconds(1));
    }