Перейти к основной части
Version: 29.4

Обходим иммитации модулей

Jest позволяет имитировать целые модули. Это полезно, когда нужно протестировать, что ваш код корректно вызывает функции из других модулей. Однако иногда может возникать необходимость использовать лишь часть тестового модуля в тестовом файле, и в этом случае уже нужно получить доступ к исходной реализации, а не только к мок версии.

Рассмотрим пример теста для функции createUser:

createUser.js
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. А это значит, что тест должен выполниться успешно.