How to Mock React Suspense
This article explains how to mock React Suspense when writing unit tests for your React applications. You will learn why mocking Suspense is sometimes necessary, the different strategies for handling asynchronous components in Jest and React Testing Library, and how to implement these solutions in your test suites.
Why Mock React Suspense?
When testing components that utilize React.lazy and
Suspense, unit tests can fail because the component
attempts to load asynchronously. If your testing environment is not
configured to wait for the lazy-loaded component to resolve, the test
will fail or only assert the state of the fallback loader.
To resolve this, you can either mock the lazy-loaded component to
render synchronously, mock the Suspense component itself,
or use asynchronous query methods to wait for the component to load.
Method 1: Mocking the Lazy-Loaded Component (Recommended)
The cleanest and most reliable way to handle React Suspense in tests
is to mock the React.lazy import. Instead of letting the
component load asynchronously, you mock the module to return a standard
synchronous component.
Suppose you have a component that loads a child component lazily:
// App.js
import React, { Suspense, lazy } from 'react';
const LazyChild = lazy(() => import('./LazyChild'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyChild />
</Suspense>
);
}In your Jest test file, mock LazyChild before running
the tests:
import { render, screen } from '@testing-library/react';
import App from './App';
// Mock the lazy component to render synchronously
jest.mock('./LazyChild', () => {
return function DummyChild() {
return <div data-testid="lazy-child">Mocked Child Component</div>;
};
});
test('renders mocked lazy component without suspense delay', () => {
render(<App />);
const childElement = screen.getByTestId('lazy-child');
expect(childElement).toBeInTheDocument();
});Method 2: Mocking the React Suspense Component Globally
If you want to completely bypass Suspense across your
entire test suite so that fallback UI never renders, you can mock
React.Suspense to immediately render its children.
Add this mock to your individual test file or your global
setupTests.js file:
import React from 'react';
jest.mock('react', () => {
const originalReact = jest.requireActual('react');
return {
...originalReact,
// Force Suspense to render its children synchronously without the fallback
Suspense: ({ children }) => children,
};
});With this mock active, React will ignore the lazy-loading boundary and attempt to render the nested children directly. Note that this requires any underlying lazy components to also be mocked, otherwise the render will fail.
Method 3: Testing the Suspense Fallback State (No Mocking)
If you actually want to test the transition from the “Loading…”
fallback state to the resolved component, you should not mock Suspense.
Instead, use React Testing Library’s asynchronous query tools
(findBy) to wait for the transition to finish.
import { render, screen } from '@testing-library/react';
import App from './App';
test('displays loading fallback and then renders lazy component', async () => {
render(<App />);
// 1. Assert the fallback state is initially visible
expect(screen.getByText(/loading.../i)).toBeInTheDocument();
// 2. Wait for the lazy component to resolve and render
const resolvedElement = await screen.findByText(/actual child content/i);
expect(resolvedElement).toBeInTheDocument();
// 3. Assert the fallback has been removed
expect(screen.queryByText(/loading.../i)).not.toBeInTheDocument();
});