Flux bufferMillis — Как тестировать?

Я пытаюсь протестировать Flux.bufferMillis с помощью виртуального планировщика, но время от времени это не удается. Ниже приведен код для

StepVerifier.withVirtualTime(new Supplier() {
    Flux get() {
        return Flux.interval(1 second).take(5).bufferMillis(1500);
    }}
)
    .thenAwait(5 seconds)
    .expectNext(...)
    .verifyComplete();

Ошибка, которую я периодически получаю, выглядит следующим образом:

java.lang.AssertionError: expectation "expectNextMatches" failed (expected: onNext(); actual: onError(java.util.concurrent.RejectedExecutionException: Scheduler unavailable))

Я не уверен, почему Scheduler иногда недоступен.


person Wins    schedule 05.03.2017    source источник
comment
Я не смог воспроизвести его в тесте JUnit в реакторе, ни на мастере, ни на теге 3.0.4.RELEASE... Это полный объем вашего теста? Любые другие тесты, выполненные в том же прогоне? Это происходит, если VirtualTimeScheduler был dispose() (или эквивалентным устаревшим shutdown)   -  person Simon Baslé    schedule 07.03.2017
comment
В основном это происходит, если тест запускается Gradle вместе с другими тестами.   -  person Wins    schedule 07.03.2017
comment
Вы можете проверить все тесты на github.com/sinwe/reactor-core-scala. в основной ветке. Сейчас ломается   -  person Wins    schedule 07.03.2017
comment
Я думаю, что это связано с scalatest поведением по умолчанию при распараллеливании тестов (см. /gradle-scalest#parallel-testing). Виртуальное время StepVerifier зависит от того, устанавливается ли SchedulerFactory последовательно, а не параллельно. Можете ли вы попробовать без тестового параллелизма, просто для уверенности?   -  person Simon Baslé    schedule 07.03.2017
comment
Спасибо, я попробую. Но это прерывисто, поэтому мне нужно запускать его несколько раз, чтобы убедиться, что он устраняет проблему.   -  person Wins    schedule 07.03.2017


Ответы (1)


StepVerifier и виртуальное время работают примерно так, когда вы просто предоставляете Supplier<Flux> и verify() это:

  1. StepVerifier получает экземпляр «виртуального планировщика времени».
  2. Он заменяет SchedulerFactory ядра на тот, который возвращает этот виртуальный планировщик времени всем операторам, которым нужен планировщик по умолчанию.
  3. Он звонит поставщику, чтобы создать цепочку операторов для тестирования, и подписывается на нее, затем воспроизводит и проверяет сценарий.
  4. Наконец, он очищает и закрывает используемый виртуальный планировщик.

Вот где могут возникнуть проблемы при параллельном запуске тестов: поскольку есть только 1 фабрика и из-за способа получения VTS, наличие 2 параллельных тестов виртуального времени может привести к использованию одного и того же экземпляра VirtualTimeScheduler в фоновом режиме. Таким образом, первый тест отключит планировщик, а второй тест будет REJECTED.

Поскольку gradle-scalatest по умолчанию работает параллельно, скорее всего, это источник вашего проблема.

person Simon Baslé    schedule 09.03.2017
comment
Спасибо, я отмечу это как ответ. Однако можно внести усовершенствования, чтобы планировщик выключался только тогда, когда на него больше нет ссылок. - person Wins; 09.03.2017
comment
Не похоже, что установка параллелизма на 1 решает проблему. Дело все еще происходит. Он проходит на моей локальной машине, но не в CI. - person Wins; 10.03.2017
comment
Хорошо, тогда происходит что-то еще ... нам нужно больше информации (трассировка стека при тестировании) и лучше всего воспроизвести ее локально. Можете ли вы открыть проблему в github реактора-аддонов и попытаться собрать трассировку стека? - person Simon Baslé; 10.03.2017
comment
подождите, в вашей последней неудачной сборке TravisCI у вас есть прогон тестов, который в порядке, затем прогон scoverage, который терпит неудачу... Вы не настроили SCoverage для последовательного запуска, так что, скорее всего, это все та же проблема. см. github.com/scoverage/gradle-scoverage/issues/ для предотвращения параллелизма - person Simon Baslé; 10.03.2017
comment
Думал, настройка test {maxParallelFork = 1} будет работать и для теста, и для охвата... Посмотрю - person Wins; 10.03.2017
comment
Возможно, вы правы, testScoverage { maxParallelForks = 1} это, наверное, то, что мне нужно. - person Wins; 10.03.2017
comment
мы поэкспериментируем с добавлением подсчета ссылок в VirtualTimeScheduler и/или упростим работу с StepVerifier + VTS, хотя это предложение имело хороший потенциал;) - person Simon Baslé; 10.03.2017
comment
Хорошо, я могу подтвердить, что testScoverage {maxParallelForks = 1} исправил сборку. Спасибо за помощь - person Wins; 11.03.2017