How to Mock JSX in React

Mocking JSX components in React is a crucial technique for unit testing, allowing you to isolate the component under test by replacing its child components with simplified, predictable alternatives. This article covers the most effective ways to mock JSX components using popular testing frameworks like Jest and Vitest, ensuring your tests remain fast, reliable, and focused.

Why Mock JSX Components?

When unit testing a parent component, you often want to avoid rendering its complex child components. Mocking child JSX components helps to: * Isolate dependencies: Test the parent component’s logic without worrying about bugs in its children. * Improve performance: Avoid rendering heavy third-party libraries or complex UI trees. * Simplify assertions: Easily verify that the child component was called with the correct props.

Method 1: Mocking ES Modules with jest.mock or vi.mock

The most common way to mock a JSX component imported from another file is to mock the module. This replaces the actual component with a dummy functional component.

Imagine you have a Parent component that renders a Child component:

// Child.jsx
export default function Child({ message }) {
  return <div>{message}</div>;
}

In your test file, you can mock the Child component like this:

import { render, screen } from '@testing-library/react';
import Parent from './Parent';

// Mock the child component module
jest.mock('./Child', () => {
  return function DummyChild({ message }) {
    return <div data-testid="mock-child">{message}</div>;
  };
});

test('renders parent with mocked child', () => {
  render(<Parent />);
  
  const mockChild = screen.getByTestId('mock-child');
  expect(mockChild).toBeInTheDocument();
});

Note: If you are using Vitest, simply replace jest.mock with vi.mock.

Method 2: Mocking Third-Party Dependency Components

If your JSX component relies on a third-party library (like a charting library or a complex icon pack), you can mock the entire library.

Here is how to mock a component from a library like react-router-dom:

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  Link: ({ children, to }) => <a href={to}>{children}</a>,
}));

Using jest.requireActual ensures you only override the JSX components you need to mock, while keeping other utility functions (like hooks) intact.

Method 3: Spying on Props

Sometimes you need to verify that a mocked JSX component received the correct props from the parent. You can achieve this by passing a Jest mock function (jest.fn()) as the implementation.

import { render } from '@testing-library/react';
import Parent from './Parent';
import Child from './Child';

jest.mock('./Child', () => jest.fn(() => <div data-testid="mock-child" />));

test('passes correct props to the child', () => {
  render(<Parent user="Alice" />);
  
  // Assert that the mock was called with specific props
  expect(Child).toHaveBeenCalledWith(
    expect.objectContaining({ name: 'Alice' }),
    expect.anything()
  );
});

Using these patterns allows you to cleanly isolate your components, resulting in faster execution times and highly reliable test suites.