How to Mock Lazy Loaded Components in React
Testing React applications that utilize code-splitting requires
handling asynchronous component loading. This article explains how to
mock React’s lazy loading mechanism (React.lazy and
Suspense) using Jest and React Testing Library, allowing
you to write fast, reliable, and synchronous unit tests without waiting
for real chunk loading.
Why Mock Lazy Loading?
When you use React.lazy(), React loads the component
dynamically. In a testing environment, this asynchronous behavior can
cause tests to fail because the component is not immediately present in
the DOM. While you can resolve this using async/await and
findBy queries, mocking the lazy-loaded component to render
synchronously is often cleaner and faster.
Method 1: Mocking the Child Component (Recommended)
The most robust way to mock lazy loading is to mock the module path
of the dynamically imported component using jest.mock().
This replaces the lazy-loaded component with a simple, synchronous dummy
component.
The Component under Test
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./MyLazyComponent'));
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
export default Dashboard;The Test File
By mocking ./MyLazyComponent directly, Jest bypasses the
dynamic import entirely.
import { render, screen } from '@testing-library/react';
import Dashboard from './Dashboard';
// Mock the lazy component to render a simple div instead
jest.mock('./MyLazyComponent', () => {
return function MockedLazyComponent() {
return <div data-testid="mocked-lazy">Mocked Component Content</div>;
};
});
describe('Dashboard Component', () => {
test('renders dashboard and mocked lazy component synchronously', () => {
render(<Dashboard />);
expect(screen.getByText('Dashboard')).toBeInTheDocument();
expect(screen.getByTestId('mocked-lazy')).toBeInTheDocument();
});
});Method 2: Mocking React.lazy Globally
If you want to disable lazy loading across all components in a test
file, you can mock React.lazy itself. This forces all lazy
components to resolve immediately.
import React from 'react';
import { render, screen } from '@testing-library/react';
import Dashboard from './Dashboard';
// Force React.lazy to import components synchronously
jest.spyOn(React, 'lazy').mockImplementation((ctor) => {
const Component = ctor().then((module) => module.default);
return (props) => {
const [ResolvedComponent, setResolvedComponent] = React.useState(null);
React.useEffect(() => {
Component.then((Comp) => setResolvedComponent(() => Comp));
}, []);
return ResolvedComponent ? <ResolvedComponent {...props} /> : null;
};
});While global mocking works, Method 1 is generally preferred because it targets individual modules and avoids overriding core React APIs.