Тестирование
На предыдущих шагах часто упоминалось, что те или иные паттерны помогают в тестировании.
Давайте рассмотрим пример теста в нашем приложении, например, проверим что при вызове метода сервиса вызывается нужное АПИ.
Для начала замокаем наше API, т. к. вряд ли мы хотим, чтобы наши unit-тесты зависели от того, сломан бэкенд или нет.
class TestAPI extends API {
fetchUser = jest.fn();
}
Поскольку мы заранее озаботились тем, чтобы между нашими сервисами и API была явная зависимость по контрактам, наш тест очень просто написать. Единственная загвоздка в том, что вся наша логика написана на генераторах, но для её выполнения во фреймворке есть хелпер getSagaRunner.
import { getSagaRunner } from '@iiiristram/sagun/test-utils';
test("request user", () => {
const runner = getSagaRunner();
return runner.run(function * ({ operationService, store }) {
const testApi = new TestAPI();
const userService = new UserService(operationService, testApi);
yield* call(userService.getUserInfo);
// проверяем что вызвалось АПИ
expect(testApi.fetchUser).toHaveBeenCalled();
// проверяем что в store появились данные
const userOperation = store.getState().asyncOperations.get(getId(userService.getUserInfo))
expect(userOperation.result.login).toBe('John Doe');
})
})
На примере этого теста хочется отметить несколько важных моментов:
- В тесте никак не участвует React, бизнес-логика тестируется изолированно.
- Благодаря явным контрактам, о которых мы заранее подумали, нам не требуется мокать экспорты файлов. На первый взгляд кажется, какая разница? Но экспорты модулей на практике разработчики редко рассматривают как контракт. Поэтому зачастую оказывается, что для написания теста либо из файла не экспортировано что-то, что требуется замокать, либо требуется мокать вообще другие модули, на которые опирается исходный модуль. Фактически для теста требуется знать внутреннее устройство модуля, что нарушает инкапсуляцию. И есть большие риски, что после обновления модуля на новую версию тест придётся полностью менять, т. к. внутреннее устройство модуля сильно изменилось (возможно, полностью переписано), хотя контракт экспортов не поменялся.