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()基盤となるものを実際に使用するため、を使用する場合、基盤となるスケジューラーは...TimedSchedulerwithVirtualTimeVirtualTimeScheduler

ただし、バグがあります。そのような演算子は、 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 に答える