Недавно я наткнулся на хороший способ тестирования наблюдаемых, который называется «мраморное тестирование». Это называется мраморным тестированием, потому что мраморные диаграммы, диаграммы в документации библиотеки, используются для подтверждения поведения и значений, а также для создания фиктивных наблюдаемых для тестируемого наблюдаемого.
Создание мраморной диаграммы в коде
Мраморные диаграммы обычно представляют собой изображения, но в наших тестах мраморная диаграмма - это просто строка, которая выглядит примерно так:
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
и значения.
Надеюсь, этот пост дал вам достаточно понимания, чтобы начать писать тесты и переходить к документации.
Спасибо.