эпики модульного тестирования при использовании redux-observable

В моем последнем посте я говорил о том, что такое промежуточное ПО, наблюдаемое за редукцией, и как вы можете применить его для решения практических задач (автосохранение).

В этом посте я покажу вам, как легко и весело провести эпическое модульное тестирование! (это и все дальнейшие каламбуры полностью предназначались) Напоминаем, что примерно так выглядел пользовательский интерфейс в предыдущем посте, в то время как эпик saveFieldEpic.js прислушивался к действиям, отправленным из события onChange этого компонента ввода. :

Перед тем, как мы начнем писать код для наших тестов, мы можем упростить тестирование, добавив зависимости во все эпики (которые мы захотим заменить позже в наших тестах) при объединении эпиков, прямо перед вызовом createEpicMiddleware (полный кредит на Джею Фелпсу за эту информацию!).

const rootEpic = (...args) => combineEpics(
    saveFieldEpic,
)(...args, {ajax});

В этом примере, когда мы создаем хранилище Redux, мы вводим ajax из rxjs/observable/dom/ajax, который теперь будет отображаться как третий аргумент в наших эпиках (сразу после action$ и store). Опять же, это сделано для того, чтобы мы могли заменить ее другой функцией во время тестирования, которая фактически не будет отправлять XHR по сети.

Код в нашем saveFieldEpic.js файле из последнего сообщения теперь будет выглядеть примерно так: мы передаем action$ в строке 14, как обычно, затем null для значения store (поскольку оно нам не понадобится) и, наконец, {ajax}.

* примечание: использование null для значения хранилища может привести к ошибкам сборки, и в этом случае вы можете просто использовать store (обновлено 23 ноября 2017 г.)

Теперь, когда мы внедрили зависимость AJAX и наша эпическая программа уже работает изолированно, мы можем приступить к тестированию входных и выходных данных самой эпической функции (без необходимости имитировать хранилище).

Импортируя ActionsObservable из библиотеки, наблюдаемой за redux, мы можем отправлять имитирующие действия в тестируемую эпопею. Затем мы можем создать нашу фиктивную версию функции AJAX, которая будет либо возвращать Observable.of({}) (или любой другой тип ответа сервера), если вызов AJAX должен быть успешным, либо Observable.throw('something bad!'), если вызов AJAX должен завершиться неудачно.

Наконец, мы импортируем эпос, скармливаем ему эти входные данные и вызываем toArray, чтобы, когда мы подписываемся на выход эпика, он возвращал массив всех действий, произведенных эпосом, в качестве выходных данных! Утверждение, что actualOutputActions глубоко равно expectedOutputActions, дает нам возможность пройти тесты!

Вот как это будет выглядеть в коде:

Я считаю эту простоту прекрасной вещью! Я также обнаружил, что этот метод остается сверхмощным при использовании в еще более сложных сценариях. И, что не менее важно, писать эти тесты - это тонна удовольствия. 🚀