How to Mock Functional Components in React

Mocking React functional components is a crucial technique in unit testing to isolate the component under test and prevent external dependencies or complex child components from affecting your test results. This article provides a straightforward guide on how to mock functional components in React using Jest and React Testing Library, covering both default and named exports with practical, easy-to-follow code examples.

Why Mock Functional Components?

When unit testing a parent component, you often want to verify its behavior without rendering its children. Mocking child components helps you: * Isolate tests: Focus purely on the parent component’s logic, state, and props. * Improve performance: Avoid rendering heavy or deeply nested child components. * Simplify assertions: Replace complex components with simple HTML placeholders that are easy to query.

Mocking Default Exports

If the functional component you want to mock is exported as a default export, you can use jest.mock() to replace the module path with a simplified dummy component.

Consider a parent component that imports a child component:

// ChildComponent.js
export default function ChildComponent({ message }) {
  return <div>Real Child Component: {message}</div>;
}

To mock this child component in your parent component’s test file, declare the mock at the top of your file:

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

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

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

Mocking Named Exports

If your component uses named exports, the mock structure changes slightly because jest.mock() must return an object containing the named component.

// ChildComponent.js
export function NamedChild({ message }) {
  return <div>Real Named Child: {message}</div>;
}

Mock the named export by returning an object where the key matches the exported component name:

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

// Mock the named export
jest.mock('./ChildComponent', () => ({
  NamedChild: ({ message }) => <div data-testid="mock-named-child">{message}</div>
}));

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

Mocking to Inspect Passed Props

Sometimes you need to verify that the parent component passes the correct props to the child component. You can achieve this by assigning a Jest mock function (jest.fn()) to the mocked component.

import { render } from '@testing-library/react';
import ParentComponent from './ParentComponent';
import ChildComponent from './ChildComponent';

// Create a mock function to capture props
const mockChildRender = jest.fn();

jest.mock('./ChildComponent', () => {
  return function MockChild(props) {
    mockChildRender(props);
    return <div data-testid="mock-child" />;
  };
});

test('passes correct props to child component', () => {
  render(<ParentComponent customProp="test-value" />);
  
  // Verify the props passed to the child component
  expect(mockChildRender).toHaveBeenCalledWith(
    expect.objectContaining({
      customProp: 'test-value'
    })
  );
});