0

根据其 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)

我原以为经过的时间至少为 1000 毫秒,但结果只有 11 毫秒。

我在这里想念什么吗?

4

1 回答 1

1

elapsed()操作员确实使用底层来TimedScheduler获取时钟“即时”以计算时间增量,所以当withVirtualTime使用时,底层调度程序应该是一个VirtualTimeScheduler......

但是有一个错误:这些操作符在使用 default 时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();
}
于 2017-01-10T14:41:32.393 回答