According to its Javadoc, Mono.elapse()
will produce Mono<Tuple2<Long, T>>
where the first value would be the elapsed time between the subscribe and the first next signal.
The following test does not work
StepVerifier.withVirtualTime(() -> Mono.just(1)
.delaySubscription(Duration.ofSeconds(1))
.elapsed(),
() -> VirtualTimeScheduler.enable(true), 1)
.thenAwait(Duration.ofSeconds(1))
.expectNextMatches(tuple2 -> tuple2.getT1() >= 1000 && tuple2.getT2() == 1)
.verifyComplete();
It will throw exception:
java.lang.AssertionError: expectation "expectNextMatches" failed (predicate failed on value: 11,1)
I was expecting that the time elapsed would be at least 1000ms, but it turns out to be just 11ms.
Do I miss anything here?
The
elapsed()
operator indeed uses an underlyingTimedScheduler
to get clock 'instants' in order to compute the time delta, so whenwithVirtualTime
is used, the underlying scheduler should be aVirtualTimeScheduler
...But there is a bug: such operators, when using a default
Scheduler
, actually obtain a common instance cached within a wrapper. The problem is that the wrapper doesn't delegate itsnow
method, which is the one used byelapsed
.Since the default implementation for
now()
is to useSystem.currentTimeMillis()
, what you effectively see is elapsed bypasses the virtual time and report real time deltas.In order to work around that, until the bug is fixed, you can explicitly create and supply a
VirtualTimeScheduler
like so: