jest.mock — мощный инструмент Jest для создания
поддельных (mock) модулей и компонентов в тестах. В контексте React
Testing Library его основная задача — изолировать тестируемый компонент,
заменяя зависимости заглушками, чтобы тесты были детерминированными и не
зависели от внешних модулей, сетевых запросов или сложных дочерних
компонентов.
Для замены модуля или компонента используется синтаксис:
jest.mock('путь/к/модулю', () => {
return {
__esModule: true, // важно для экспорта по умолчанию
default: () => <div>Mocked Component</div>,
namedExport: jest.fn()
};
});
__esModule: true — требуется, если модуль
экспортируется через export default.default — замена default-экспорта компонента.namedExport — можно мокать отдельные именованные
экспорты.После такого объявления, при импорте модуля внутри тестируемого файла будет использоваться мок, а не реальная реализация.
Частая задача — заменить дочерний компонент, чтобы тестировать только родителя:
import { render, screen } from '@testing-library/react';
import ParentComponent from './ParentComponent';
import ChildComponent from './ChildComponent';
jest.mock('./ChildComponent', () => () => <div>Mocked Child</div>);
test('отображает родительский компонент с замещённым дочерним', () => {
render(<ParentComponent />);
expect(screen.getByText('Mocked Child')).toBeInTheDocument();
});
В этом примере реальная реализация ChildComponent не
выполняется, что ускоряет тесты и предотвращает побочные эффекты.
Если компонент использует функции из других модулей, их также можно замокать:
import { fetchData } from './api';
import MyComponent from './MyComponent';
jest.mock('./api', () => ({
fetchData: jest.fn(() => Promise.resolve({ data: 'mocked data' }))
}));
test('использует замоканную функцию fetchData', async () => {
render(<MyComponent />);
const item = await screen.findByText('mocked data');
expect(item).toBeInTheDocument();
});
jest.fn() для создания шпионов и
замоканных реализаций.toHaveBeenCalled()
и toHaveBeenCalledWith().jest.mock()Если не передавать второй аргумент, Jest автоматически создаст мок:
jest.mock('./ChildComponent');
jest.fn().import ChildComponent from './ChildComponent';
ChildComponent.mockImplementation(() => <div>Custom Mock</div>);
Для классовых компонентов принцип такой же, но нужно правильно обработать методы:
jest.mock('./MyClassComponent', () => {
return jest.fn().mockImplementation(() => ({
render: () => <div>Mocked Class Component</div>
}));
});
render.jest.fn().Иногда требуется менять поведение мока только для одного теста:
import ChildComponent from './ChildComponent';
test('разное поведение мока', () => {
ChildComponent.mockImplementation(() => <div>First Mock</div>);
render(<ParentComponent />);
expect(screen.getByText('First Mock')).toBeInTheDocument();
ChildComponent.mockImplementation(() => <div>Second Mock</div>);
render(<ParentComponent />);
expect(screen.getByText('Second Mock')).toBeInTheDocument();
});
mockImplementation позволяет динамически менять
реализацию.jest.resetAllMocks() или mockRestore() для
восстановления оригинальных реализаций.Можно использовать пропсы для проверки взаимодействий:
jest.mock('./Button', () => ({ onClick, label }) => (
<button onCl ick={onClick}>{label}</button>
));
test('вызывает onClick у замоканного Button', () => {
const handleClick = jest.fn();
render(<MyComponent onCl ick={handleClick} />);
const button = screen.getByText('Click me');
button.click();
expect(handleClick).toHaveBeenCalled();
});
jest.mock с React Testing LibrarymockImplementation для создания разных
сценариев в тестах.Использование jest.mock позволяет писать быстрые,
надёжные и предсказуемые тесты, концентрируясь на поведении конкретного
компонента, а не на реализации его зависимостей.