Mono.elapse 不适用于 StepVerifier?

Mono.elapse does not work with StepVerifier?

根据其 Javadoc,Mono.elapse() 将生成 Mono<Tuple2<Long, T>>,其中第一个值是订阅和第一个下一个信号之间经过的时间。

以下测试无效

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();

会抛出异常:

java.lang.AssertionError: expectation "expectNextMatches" failed (predicate failed on value: 11,1)

我原以为流逝的时间至少是1000ms,但结果只有11ms。

我在这里有什么遗漏吗?

elapsed() 运算符确实使用底层 TimedScheduler 来获取时钟 'instants' 以计算时间增量,因此当使用 withVirtualTime 时,底层调度程序应该是 VirtualTimeScheduler...

但是有一个错误:当使用默认值 Scheduler 时,此类运算符实际上获得了一个缓存在包装器中的公共实例。问题是包装器没有委托其 now 方法,这是 elapsed.

使用的方法

由于 now() 的默认实现是使用 System.currentTimeMillis(),您有效地看到的是经过的绕过虚拟时间并报告实时增量。

为了解决这个问题,在错误修复之前,您可以显式创建并提供一个 VirtualTimeScheduler,如下所示:

@Test
public void elapsedWithVirtualTimeWorkaround() {
    //we have to create a reference that will be used in 2 places
    VirtualTimeScheduler vts = VirtualTimeScheduler.create();

    StepVerifier.withVirtualTime(() -> Mono.just(1)
                                           .delaySubscription(Duration.ofSeconds(1))
                                           .elapsed(vts), //this avoids the cache problem
            () -> vts, //the supplied scheduler here will be automatically activated by StepVerifier
            1)
                .thenAwait(Duration.ofSeconds(1)) //this uses the same vts once again
                .expectNextMatches(tuple2 -> tuple2.getT1() >= 1000 && tuple2.getT2() == 1)
                .verifyComplete();
}