ES6 модулей
Вот пример ES6:
helperFn.js
export default () => 'original';
code.js
import helperFn from './helperFn';
export const func = () => helperFn();
code.test.js
import * as helperFnModule from './helperFn';
import { func } from './code';
describe('helperFn mocked', () => {
let mock;
beforeEach(() => {
mock = jest.spyOn(helperFnModule, 'default');
mock.mockReturnValue('mocked');
});
afterEach(() => {
mock.mockRestore();
});
test('func', () => {
expect(func()).toBe('mocked'); // Success!
});
});
describe('helperFn not mocked', () => {
test('func', () => {
expect(func()).toBe('original'); // Success!
});
});
Детали
Поскольку ES6-импорт представляет собой оперативные представления об экспорте модуля, экспорт легко смоделируется, а затем восстанавливается.
Модули Node.js
Вот пример Node.js:
helperFn.js
exports.default = () => 'original';
code.js
const helperFn = require('./helperFn').default;
exports.func = () => helperFn();
code.test.js
describe('helperFn mocked', () => {
beforeEach(() => {
const helperFnModule = require('./helperFn');
helperFnModule.default = jest.fn(() => 'mocked');
});
afterEach(() => {
jest.resetModules();
});
test('func', () => {
const { func } = require('./code');
expect(func()).toBe('mocked'); // Success!
});
});
describe('helperFn not mocked', () => {
test('func', () => {
const { func } = require('./code');
expect(func()).toBe('original'); // Success!
});
});
Детали
Экспорт default
запоминается code.js
при запуске, поэтому изменение экспорта default
helperFn.js
не влияет на func
, если code.js
равно required
. Jest
также кэширует модули и возвращает один и тот же модуль для нескольких вызовов require
, если не вызывается jest.resetModules
.
Таким образом, для модулей Node.js часто проще всего require
кодировать в самом тесте и использовать jest.resetModules
для сброса любых насмешек.