How to Mock React Components
Mocking React components is a crucial technique in unit testing that allows you to isolate the component under test by replacing its child dependencies with dummy implementations. This article provides a straightforward guide on how to mock React components using Jest and React Testing Library, covering both basic mock setups and custom mock implementations to keep your tests fast, reliable, and focused.
Why Mock React Components?
When unit testing a parent component, you often want to avoid rendering its complex child components. Mocking child components helps to: * Isolate tests: Ensure you are only testing the behavior of the component in question. * Increase speed: Avoid rendering heavy third-party libraries or deeply nested component trees. * Simplify assertions: Easily verify if the child component received the correct props without worrying about its internal behavior.
Mocking a Component with Jest
The most common way to mock a React component is by using
jest.mock(). This tells Jest to replace the imported module
with a mocked version.
Consider a parent component Dashboard that imports a
complex HeavyChart component:
// Dashboard.js
import React from 'react';
import HeavyChart from './HeavyChart';
const Dashboard = () => {
return (
<div>
<h1>User Dashboard</h1>
<HeavyChart data={[1, 2, 3]} />
</div>
);
};
export default Dashboard;To test Dashboard without rendering the actual
HeavyChart, you can mock the child component in your test
file.
Default Mocking (Automatic Mock)
If you just want to prevent the child component from rendering its real content, you can mock it at the top of your test file:
// Dashboard.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import Dashboard from './Dashboard';
// Mock the child component
jest.mock('./HeavyChart', () => {
return function DummyChart() {
return <div data-testid="mock-heavy-chart">Mocked Chart</div>;
};
});
test('renders Dashboard with mocked HeavyChart', () => {
render(<Dashboard />);
expect(screen.getByText('User Dashboard')).toBeInTheDocument();
expect(screen.getByTestId('mock-heavy-chart')).toBeInTheDocument();
});Mocking Components with Props
Often, you need to verify that the parent component passes the correct props to the child component. You can capture and assert these props in your mock.
// Dashboard.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import Dashboard from './Dashboard';
// Mock the child component and capture its props
jest.mock('./HeavyChart', () => {
return function DummyChart({ data }) {
return (
<div data-testid="mock-heavy-chart">
Mocked Chart Data Length: {data.length}
</div>
);
};
});
test('passes correct data props to HeavyChart', () => {
render(<Dashboard />);
const chartElement = screen.getByTestId('mock-heavy-chart');
expect(chartElement).toHaveTextContent('Mocked Chart Data Length: 3');
});Mocking Third-Party React Components
You can use the same technique to mock components imported from external npm packages, such as icon libraries or routing packages.
For example, to mock a component from
react-router-dom:
import React from 'react';
import { render, screen } from '@testing-library/react';
import Navigation from './Navigation';
// Mock the Link component from react-router-dom
jest.mock('react-router-dom', () => ({
Link: ({ to, children }) => <a href={to}>{children}</a>,
}));
test('renders mocked navigation link', () => {
render(<Navigation />);
const linkElement = screen.getByRole('link', { name: /home/i });
expect(linkElement).toHaveAttribute('href', '/home');
});