Здравствуйте, люди 👋! Сегодня пришло время говорить о тестировании и как проверить код, когда мы используем RXJS. Прежде чем переместить наше внимание на тестирование, мне нужно объяснить два разных типа наблюдаемых: холодные и горячие.
Когда вы создаете наблюдаемый, вы можете создать горячий или холодный наблюдаемый. Эта характеристика зависит от того, где установлен производитель этого наблюдаемого; Когда производитель создается наблюдаемым, наблюдаемый является «холодным», вместо этого, когда производитель создан из наблюдаемого, он определен «горячий». Позвольте мне пролить свет на все эти слова. Что упроизвести? Производитель является источником значений нашего наблюдаемого. Холодные наблюдатели Холодные наблюдаемые являются функциями, которые создают производитель и управлять этим для всей его жизни. Холод наблюдаемый отвечает за эти вещи:
- Создать производителя
- активировать производителя
- начать слушать производителю
- бездельничать
- Закройте производителя
Вот пример:
const source = new Observable((observer) => { const socket = new WebSocket('ws://someurl'); socket.addEventListener('message', (e) => observer.next(e)); return () => socket.close(); });
Горячие наблюдаемые Необходимый «горячий», если его базовый производитель либо создан, либо активирован вне подписки.
- Разделяет ссылку на производителя
- Начинает слушать производителю
- многоадресная передача (обычно)
Вот пример:
const socket = new WebSocket('ws://someurl'); const source = new Observable((observer) => { socket.addEventListener('message', (e) => observer.next(e)); });
Хорошо, я думаю, что теперь у вас есть идея разницы между этими двумя типами, и я могу перейти к теме дня, но если вы заинтересованы в углублении этого аргумента здесь это сообщение о горячей и холодной, написанном Бен Лес Отказ
Чтобы проверить наш код в RXJS мы используем мраморные тестирования. Способ, который сочетает в себе мраморную диаграмму с кодом, и позволяет нам представить поведение наших наблюдаемых и перевести их на то, что может понять структуру тестирования.
Мраморный синтаксис
Как вы можете себе представить, мраморное тестирование имеет свой собственный синтаксис для представления поведения и здесь вы можете найти его правила:
- Whitespace: Горизонтальное пробеловое пространство игнорируется и может использоваться для того, чтобы помочь вертикально выровнять несколько мраморных диаграмм.
-
Рамка: 1 “Рамка” виртуального прохождения времени (см. Выше описание кадров).[0-9] + [MS | S | M]
Прогрессирование времени: синтаксис времени прогрессирования позволяет вам прогрессировать виртуальное время на определенную сумму. Это число, которое следуют единицей временного устройства MS (миллисекунды), S (секунды) или M (минуты) без какого-либо места между ними, например, E.g. 10 мс. b.|.
Заполните: успешное завершение наблюдаемого. Это наблюдаемая сигнализация производителя ().#
Ошибка: ошибка завершается наблюдаемым. Это наблюдаемая ошибка сигнализации производителя ().[A-Z0-9]
например «А» любой буквенно-цифровой символ: Представляет значение, испускаемое производителем сигнализирующей следующей ().()
Синхронизация группировки: когда несколько событий должны быть в одном кадре синхронно, скобки используются для группировки этих событий.^
Точка подписки: (только горячие наблюдаемые только) показывает точку, в которой тестируемые наблюдаемые будут подписаны на горячую наблюдаемый. Это «нулевая рама» для того, чтобы наблюдаемая, каждый кадр до ^ будет отрицательным. Негативное время может показаться бессмысленным, но на самом деле существуют продвинутые случаи, когда это необходимо, обычно включающее воспроизведение.
Testscheduler.
TestsCheduler – это волшебник, который переводит мраморный синтаксис к тому, что тестовые рамки могут понять. Важно помнить, что мы не можем использовать TestsCheduler, чтобы все время проверить наш код. Например, если код потребляет обещание, мы не можем использовать его, но мы должны использовать традиционный метод. TestsCheduler предоставляет нам некоторые API, которые мы можем использовать для записи наших тестов, но мы начинаем с его инициализации.
import { TestScheduler } from 'rxjs/testing'; describe('Marble Testing', () => { let testScheduler: TestScheduler; beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); }); });
N.B. Все примеры использовать шума в качестве структуры тестирования
Как видите, важно создать новый TestsCheduler для каждого теста, это позволяет нам иметь новый экземпляр для каждого теста и создать чистый случай. Но странная вещь в этом коде является телом кода, проходящего в TestScheduler. Этот код имеет особый, если вы уверены в себе любые тестовые рамки, потому что в этой функции мы уже указывали ожидания теста, но мы еще не написали. Это, поскольку TestsCheduler обнажает некоторые помощники для проверки кода, и эти помощники вызывают функцию, указанную в конструкторе TestScheduler, чтобы проверить сбой или успех теста.
Но давайте посмотрим конкретный пример:
import { TestScheduler } from 'rxjs/testing'; describe('Marble Testing', () => { let testScheduler: TestScheduler; beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); }); it('test', () => { testScheduler.run((helpers) => { const { cold, expectObservable } = helpers; const source$ = cold('-a-b-c|'); const expected = '-a-b-c|'; expectObservable(source$).toBe(expected); }); }); });
В этом примере мы создали холодный наблюдаемый, который излучает 3 значения: A, B и C. Использование ожидаемого помощника, мы можем проверить наше наблюдаемое, сравнивая его с ожиданием, переданным методу TOBE. Теперь давайте добавим динамизм на наши тесты и посмотрим, как пройти значения нашим наблюдаемым внутри тестов.
import { TestScheduler } from 'rxjs/testing'; describe('Marble Testing', () => { let testScheduler: TestScheduler; beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); }); it('test with values', () => { testScheduler.run((helpers) => { const { cold, expectObservable } = helpers; const source$ = cold('-a-b-c|', { a: 1, b: 2, c: 3 }); const expected = '-a-b-c|'; expectObservable(source$).toBe(expected, { a: 1, b: 2, c: 3 }); }); }); });
В этом примере вы можете видеть, что мы можем пройти другой аргумент к холодной функции. Этот аргумент является объектом, в котором поля являются корреспондентами значения, передаваемых в мраморной строке, поэтому, если вы используете A, B и C в мраморной строке, вы должны использовать A, B и C в виде поля вашего аргумента. Значения этих полей являются значениями, используемыми тестом и испускаемыми наблюдаемыми. То же самое касается метода TOBE, он принимает еще один аргумент, в котором мы можем пройти ожидаемые значения результата. Еще одна важная концепция, когда вы тестируете свои наблюдаемые, – это время, в этих случаях можно указать после того, как время наблюдается наблюдаемое значение или после того, как ожидается значение значения. Здесь пример с использованием CONCATMAP
Оператор в сочетании с задержка
Оператор, который задерживает результат на 100 мс.
import { concatMap, delay, of } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; describe('Marble Testing', () => { let testScheduler: TestScheduler; beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); }); it('test', () => { testScheduler.run((helpers) => { const { cold, expectObservable } = helpers; const source$ = cold('-a-b-c|'); const final$ = source$.pipe(concatMap(val => of(val).pipe(delay(100)))); const expected = '- 100ms a 99ms b 99ms (c|)'; expectObservable(final$).toBe(expected); }); }); });
В предыдущих примерах я показал вам, как тестировать холодные наблюдаемые, но вы также можете испытать горячие наблюдаемые. Одна из важных концепций, когда вы создаете горячую наблюдаемый, состоит в том, что вы можете указать, когда наблюдаемые подписаны, и вы можете сделать это, используя ^
персонаж. Когда вы указываете подписку, вы можете вспомнить, что ваши результаты начинаются с подписки, а значения, излучаемые ранее, игнорируются тестом. Вы можете увидеть пример ниже.
import { TestScheduler } from 'rxjs/testing'; describe('Marble Testing', () => { let testScheduler: TestScheduler; beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); }); it('test', () => { testScheduler.run((helpers) => { const { hot, expectObservable } = helpers; const source$ = hot('-a-b-^-c|'); const expected = '--c|'; expectObservable(source$).toBe(expected); }); }); });
Последний тестовый случай, который я покажу вам сегодня, – это то, как проверить подписки. Иногда можно было бы необходимость проверить, когда наблюдаемый подписан и за сколько времени. Позвольте мне использовать пример: у нас есть два наблюдателя, объединенные вместе, используя оператор CONCAT, в этом случае нам необходимо проверить, подписан ли первым наблюдаемым, и когда он будет завершен, нам необходимо проверить, подписан ли второй наблюдаемый. Пока вы находитесь до этих случаев, вам нужно использовать Expectedubscriptions
помощник. Этот помощник позволяет вам проверить подписки наблюдаемых и обнаруживаемых, когда наблюдаемый подписан и когда отписался. Здесь вы можете найти пример, поясненный выше.
import { concat } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; describe('Marble Testing', () => { let testScheduler: TestScheduler; beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); }); it('test subscriptions', () => { testScheduler.run((helpers) => { const { cold, expectObservable, expectSubscriptions } = helpers; const source1$ = cold('-a-b-c|'); const source2$ = cold('-d-e-f|'); const final$ = concat(source1$, source2$); const expected = '-a-b-c-d-e-f|'; const expectedSubscriptionsSource1 = '^-----!'; const expectedSubscriptionsSource2 = '------^-----!'; expectObservable(final$).toBe(expected); expectSubscriptions(source1$.subscriptions).toBe(expectedSubscriptionsSource1); expectSubscriptions(source2$.subscriptions).toBe(expectedSubscriptionsSource2); }); }); });
Хорошо, ребята, я думаю, что это достаточно на сегодня. Здесь Вы можете найти код этой статьи. Но прежде чем я отпущу тебя, у меня плохие новости, к сожалению, это последняя статья сериала, поэтому сегодня будут особые уважения. Я надеюсь, что вам понравилось эту серию, и вы лучше поняли мир RXJS. Спасибо, что прочитав сериал, и если у вас есть какие-либо сомнения, не стесняйтесь обращаться ко мне, я буду рад помочь вам.
Я скоро вернусь с новым содержанием, увидимся в ближайшее время, ребята, оставайтесь подписчитыми, а до свидания.
Оригинал: “https://dev.to/this-is-learning/rxjs-marble-testing-2gg9”