Jest
может смоделировать весь модуль, используя jest.mock()
, или смоделировать экспорт отдельного модуля, используя jest.spyOn()
в сочетании с такими функциями, как mockImplementation()
.
Это позволяет легко смоделировать функцию, импортированную из библиотеки:
// ---- lib.js ----
export function myFunctionA() {
return 'a';
}
// ---- myModule.js ----
import { myFunctionA } from './lib';
export function myFunctionB() {
return myFunctionA() + 'b'; // call lib.myFunctionA()
}
// ---- myModule.test.js ----
import { myFunctionB } from './myModule';
import * as lib from './lib';
describe('myModule tests', () => {
test('myFunctionB works', () => {
const mock = jest.spyOn(lib, 'myFunctionA'); // create a spy on lib.myFunctionA()
mock.mockImplementation(() => 'c'); // replace the implementation
expect(myFunctionB()).toBe('cb');
mock.mockRestore(); // remove the spy and mock implementation
});
});
В примере кода из вопроса myModule
содержит две функции, и одна вызывает другую напрямую.
Поскольку макет работает как с целым модулем, так и с экспортом модуля, имитировать прямой вызов myFunctionA()
из myFunctionB()
будет очень сложно при написании кода.
Самый простой способ, который я нашел для обхода подобных ситуаций, - импортировать модуль в себя и использовать модуль при вызове функции. Таким образом вызывается экспорт модуля, который можно смоделировать в тесте:
// ---- myModule.js ----
import * as myModule from './myModule';
export function myFunctionA() {
return 'a';
}
export function myFunctionB() {
return myModule.myFunctionA() + 'b'; // call myModule.myFunctionA()
}
// ---- myModule.test.js ----
import * as myModule from './myModule';
describe('myModule tests', () => {
test('myFunctionB works', () => {
const mock = jest.spyOn(myModule, 'myFunctionA'); // create a spy on myModule.myFunctionA()
mock.mockImplementation(() => 'c'); // replace the implementation
expect(myModule.myFunctionB()).toBe('cb');
mock.mockRestore(); // remove the spy and mock implementation
});
});