Не перестаю находить что-то новое
Спустя 2 года работы в проекте, обнаружил у нас несколько тестов с использованием фреймворка nock. Он нужен чтобы мокать сетевые вызовы к другим сервисам (аналог wiremock).
Как это работает
Каждый мок сначала создаётся, а затем донастраивается цепочкой вызовов (builder pattern). Давай разберём на простом примере:
nock('https://some-remote-service.net',
{
reqheaders: {
authorization: 'bart',
'user-agent': 'my-super-service',
host: 'some-remote-service.net',
},
})
.post('/api/endpoint', { first_name: 'bart', last_name: 'simpson' })
.times(1)
.reply(200, {});
// вызываем тестируемый код тут
expect(nock.isDone()).toBeTruthy();
nock()
- мы говорим фреймворку слушать запросы к хосту https://some-remote-service.net
. Вторым параметром
мы передаём набор http-заголовков, которые должны быть в запросе.
.post()
- мы ожидаем запрос типа POST по пути /api/endpoint
и с телом запроса { first_name: 'bart', last_name: 'simpson' }
.
times()
- сколько раз нужно ответить на запрос.
reply()
- кот ответа и тело ответа если нужно.
nock.isDone()
- проверяет что все настроенные вызовы были сделаны. Это мне прям очень понравилось, потому что
у меня не раз были ситуации, когда вызов рельного сервиса или библиотеки поменялся, а тесты с моками продолжали работать.
Потому что замокано было что-то не то или не так, но результат оказывался правильный по счастливому стечению обстоятельств.
Пример проверки retry-логики
it('retries on error', async () => {
jest.setTimeout(10000);
nock(serviceUrl, requestOptions)
.get(firstEndpoint)
.times(4)
.reply(404);
nock(serviceUrl, requestOptions)
.post(secondEndpoint, requestBody)
.times(4)
.reply(500, {});
// вызываем тестирвемый код тут
expect(nock.isDone()).toBeTruthy();
});
Всё примерно то же самое, только вместо “хорошего” ответа 200, мы отвечаем 404 на GET по первому пути и 500 на POST по второму.
И так 4 раза. nock.isDone()
проверит, что каждый из запросов был вызван как минимум 4 раза. Пришлось поднять дефолтный
таймаут для этого теста используя jest.setTimeout()
(мы используем jest в качестве основного
тестового фреймворка).
Как это отлаживать
Параметры сетевых запросов не всегда очевидны, поэтому есть пара полезных функций для отладки:
nock(serviceUrl, requestOptions)
.get(firstEndpoint)
.times(4)
.reply(404)
.log(console.log);
Если добавить к моку (ноку?) .log(console.log)
, он будет выводить в консоль информацию о попытках сматчить сетевой запрос:
console.log node_modules/nock/lib/interceptor.js:332
matching https://some-remote-service.net/api/endpoint to POST https://some-remote-service.net:443/api/endpoint: true
true
в конце строки означает что ожидаемый запрос был получен.
Если nock.isDone()
по неведомой причине возвращает false
в конце теста, можно посмотреть, какие из моков не были вызваны:
if (nock.isDone()) {
console.log(nock.pendingMocks())
}
Сам фреймворк может намного больше, но описанного мной хватает для тестирования большинства сетевых взаимодействий. Остальное - читай в доках по ссылке в начале статьи.
comments powered by Disqus