Mono.elapse не работает со 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)

Я ожидал, что прошедшее время составит не менее 1000 мс, но оказалось, что это всего 11 мс.

Я что-то здесь пропускаю?


person Wins    schedule 09.01.2017    source источник


Ответы (1)


Оператор elapsed() действительно использует базовый TimedScheduler для получения «моментов» часов для вычисления временной дельты, поэтому, когда используется withVirtualTime, базовый планировщик должен быть _4 _...

Но есть ошибка: такие операторы при использовании значения по умолчанию 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();
}
person Simon Baslé    schedule 10.01.2017
comment
открыл github.com/reactor/reactor-core/issues/351, который должен быть исправлен в 3.0.5 - person Simon Baslé; 10.01.2017