reactor-core
reactor-core copied to clipboard
expectNoEvent does not fail on emission
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:
- Use
StepVerifier.createinstead ofwithVirtualTime - Use
thenCancel().verify()instead ofverifyTimeout(apparently a known case since #1440)
Your Environment
- Reactor version(s) used: reactor-core and reactor-test 3.4.24 (also reproducible on 3.5.2)
- JVM version (
java -version): Temurin-17.0.4+8 - OS and version (eg
uname -a): Darwin Kernel Version 21.6.0
@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));
}