Обходим иммитации модулей
Jest позволяет имитировать целые модули. Это полезно, когда нужно протестировать, что ваш код корректно вызывает функции из других модулей. Однако иногда может возникать необходимость использовать лишь часть тестового модуля в тестовом файле, и в этом случае уже нужно получить доступ к исходной реализации, а не только к мок версии.
Рассмотрим пример теста для функции createUser
:
import fetch from 'node-fetch';
export const createUser = async () => {
const response = await fetch('https://website.com/users', {method: 'POST'});
const userId = await response.text();
return userId;
};
C помощью "заглушки" fetch
можно проверить, вызывается ли оригинальная функция, не создавая при этом сетевой запрос. Однако возвращаемое значение функции fetch
нужно также сымитировать, используя класс Response
(обёрнутый в Promise
). Изначально, тест может выглядеть следующим образом:
jest.mock('node-fetch');
import fetch, {Response} from 'node-fetch';
import {createUser} from './createUser';
test('createUser calls fetch with the right args and returns the user id', async () => {
fetch.mockReturnValue(Promise.resolve(new Response('4')));
const userId = await createUser();
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith('https://website.com/users', {
method: 'POST',
});
expect(userId).toBe('4');
});
Однако, если вы запустите данный тест, функция createUser
вернёт ошибку: TypeError: response.text is not a function
. Это происходит потому, что класс Response
из библиотеки node-fetch
был сымитирован (вызов jest.mock
в начале файла) и ведёт себя по-другому.
Для решения этой проблемы используйте вспомогательную функцию jest.requireActual
. Чтобы тест заработал, добавьте следующие изменения в тестовом файле:
// BEFORE
jest.mock('node-fetch');
import fetch, {Response} from 'node-fetch';
// AFTER
jest.mock('node-fetch');
import fetch from 'node-fetch';
const {Response} = jest.requireActual('node-fetch');
Теперь, вместо имитированного, мы используем настоящий класс Response
из node-fetch
. А это значит, что тест должен выполниться успешно.