How to Mock Class Components in React

Testing legacy React applications often requires isolating components by mocking their children, some of which may still be written as Class Components. This article provides a direct, practical guide on how to mock React Class Components using Jest and React Testing Library. You will learn how to replace a Class Component with a dummy mock and how to spy on or mock specific class methods during unit testing.

Mocking the Entire Class Component

The most common scenario is wanting to mock a child Class Component to prevent it from rendering its actual implementation, which might involve complex API calls or side effects. You can achieve this by using jest.mock() to replace the module with a simple functional component.

Suppose you have a Class Component named ExpensiveClassComponent:

// ExpensiveClassComponent.js
import React, { Component } from 'react';

export default class ExpensiveClassComponent extends Component {
  render() {
    return <div>Complex and expensive rendering logic...</div>;
  }
}

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

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

// Mock the class component module
jest.mock('./ExpensiveClassComponent', () => {
  return function MockedClassComponent(props) {
    return <div data-testid="mock-expensive-component">Mocked Component</div>;
  };
});

test('renders parent component with mocked child', () => {
  render(<ParentComponent />);
  
  // Verify that the mocked version is rendered instead of the real one
  expect(screen.getByTestId('mock-expensive-component')).toBeInTheDocument();
});

Mocking Class Methods

If you need to test the component itself but want to mock a specific method on its class prototype (such as an API call or event handler), you can use jest.spyOn() targeting the class prototype.

Consider this Class Component with a custom method:

// MyClassComponent.js
import React, { Component } from 'react';

export default class MyClassComponent extends Component {
  fetchData() {
    // Real API call logic
    return fetch('/api/data').then(res => res.json());
  }

  render() {
    return <div>Class Component</div>;
  }
}

To mock only the fetchData method while keeping the rest of the component intact, spy on the class prototype before rendering the component in your test:

// MyClassComponent.test.js
import React from 'react';
import { render } from '@testing-library/react';
import MyClassComponent from './MyClassComponent';

test('mocks a specific class method', () => {
  // Spy on and mock the prototype method
  const fetchDataSpy = jest.spyOn(MyClassComponent.prototype, 'fetchData')
    .mockImplementation(() => Promise.resolve({ data: 'mocked data' }));

  render(<MyClassComponent />);

  // Assertions can check if the method was defined or called during lifecycle
  expect(fetchDataSpy).not.toHaveBeenCalled(); // or toHaveBeenCalled() if called on mount

  // Clean up the spy after the test
  fetchDataSpy.mockRestore();
});

Using these two approaches, you can easily control the behavior of React Class Components in your test environment, keeping your unit tests fast, predictable, and isolated.