Недавно я наткнулся на хороший способ тестирования наблюдаемых, который называется «мраморное тестирование». Это называется мраморным тестированием, потому что мраморные диаграммы, диаграммы в документации библиотеки, используются для подтверждения поведения и значений, а также для создания фиктивных наблюдаемых для тестируемого наблюдаемого.

Создание мраморной диаграммы в коде

Мраморные диаграммы обычно представляют собой изображения, но в наших тестах мраморная диаграмма - это просто строка, которая выглядит примерно так:

const input$ = "--a----b--c|";

Он представляет события, происходящие в «виртуальном времени».

Синтаксис

  • -: представляет кадр, и он равен 1ms виртуального времени для нашей наблюдаемой. Есть возможность настроить количество виртуального времени.
  • [a-z0-9]: представляет значение, испускаемое наблюдаемым, и увеличивает время на один кадр.
  • (abc): группирует несколько значений, которые, как ожидается, будут переданы в одном кадре. Он также увеличивает виртуальное время на выдаваемые числовые значения плюс 2 для ().
  • [0-9](ms|s|m): представляет количество виртуального времени, вы можете использовать его как замену -.
  • |: представляет собой полный сигнал, т. Е. Наблюдаемый завершился и ему больше нечего излучать.
  • #: представляет ошибку, создаваемую наблюдаемым.
  • ^ (только в «горячих» наблюдаемых): представляет момент времени, когда ожидается подписка, и представляет кадр 0, поэтому --^--a--b--| показывает, что подписка ожидается на ^. Фреймы перед ^ - -ve, а фреймы после него - + ve.
  • !: обозначают точку отказа от подписки.

Примечание. И ^, и ! можно использовать для утверждения, когда наблюдаемый объект был подписан и на который отписался, а также для указания, когда нужно подписаться и отписаться от наблюдаемого объекта. Я добавил несколько примеров, чтобы прояснить ситуацию.

Горячие и холодные наблюдаемые

Прежде чем мы начнем писать тесты, важно понять разницу между горячими и холодными наблюдаемыми. Есть несколько способов описать горячие и холодные наблюдаемые, поэтому я предлагаю прочитать об этом немного здесь.

Самое простое объяснение состоит в том, что в горячем наблюдаемом производитель не является частью наблюдаемого и выдает значения независимо от того, есть ли у него подписчики или нет, например, наблюдаемое событие перемещения мыши.

Холодный наблюдаемый объект выдает значения только тогда, когда он подписан; производитель создается, когда наблюдаемое подписано, например, запрос ajax с оператором ajax.

Узнать больше о наблюдаемом горячем и холодном.

Пора написать тесты

Давайте протестируем наблюдаемую, которая выдает два значения с интервалом 10 мс, увеличивает их на 1 и затем завершает работу.

Импортируйте TestScheduler из rxjs/testing, создайте его экземпляр с функцией для выполнения утверждения. Я использую TestScheduler для простоты, но вы также можете использовать rxjs-marbles или jest-marbles для написания мраморных тестов.

Напишем, наконец, наш тест. Мы можем представить поведение input$ на мраморной диаграмме как10ms a 9ms (b|). Почему 9 мсек, если значения выдаются через 10 мс? потому что, как и-, символ, представляющий значение, также продвигает кадр на 1 мс виртуального времени, поэтому, когда будет выдано a, пройдет 11 мс виртуального времени, и из-за этого второе значение b будет выдано через 9 мс после a и observable завершится в этом кадре, поэтому полный сигнал сгруппирован с b.

Мы передали функцию scheduler.run(), которая будет вызываться с некоторыми помощниками для имитации горячих и холодных наблюдаемых для тестируемого наблюдаемого, утверждений очереди и т. Д. Один из этих помощников - expectObservable, мы будем использовать его для постановки в очередь нашего утверждения. Утверждения выполняются синхронно после выполнения нашего обратного вызова. Мы также можем запускать утверждения во время выполнения нашего обратного вызова, вызывая helpers.flush(), но scheduler.run() все равно делает это за нас.

Давайте напишем еще один тест для наблюдаемого, который подписывается на наблюдаемый входных событий.

наш тест будет выглядеть примерно так:

Еще одна вещь, которую вы можете контролировать, - это когда TestScheduler подписывается на наблюдаемое при тестировании и отписывается от него. expectObservable helper принимает второй строковый аргумент под названием «мрамор подписки», который делает это.

С subMarble TestScheduler получает указание подписаться на output$ кадр до того, как input$ испускает какое-либо значение, и отказаться от подписки на output$ два кадра после того, как он выпустит свое первое значение. Из-за досрочной отмены подписки TestScheduler получает только одно значение, то есть a, поэтому нам пришлось обновить outputMarbles и значения.

Надеюсь, этот пост дал вам достаточно понимания, чтобы начать писать тесты и переходить к документации.

Спасибо.