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.

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.