How to Mock Redux Dispatch in React

This article provides a straightforward guide on how to mock the Redux useDispatch hook in React applications for unit testing. You will learn how to mock the react-redux module using Jest and write assertions to verify that your React components dispatch the correct actions when triggered.

The Mocking Approach

When unit testing React components that use Redux, you often want to isolate the component from the actual Redux store. Instead of configuring a real store, you can mock the useDispatch hook using Jest. This allows you to spy on the dispatch function and assert that it was called with the expected action.

Here is a step-by-step implementation.

1. The React Component

Consider a simple button component that dispatches an action to increment a counter:

// CounterButton.js
import React from 'react';
import { useDispatch } from 'react-redux';

export const CounterButton = () => {
  const dispatch = useDispatch();

  const handleClick = () => {
    dispatch({ type: 'INCREMENT' });
  };

  return <button onClick={handleClick}>Increment</button>;
};

2. Writing the Test with Jest

To test this component, mock react-redux using jest.mock(). You will override useDispatch to return a mock function (jest.fn()), which you can then inspect in your test assertions.

// CounterButton.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { useDispatch } from 'react-redux';
import { CounterButton } from './CounterButton';

// Mock the react-redux library
jest.mock('react-redux', () => ({
  ...jest.requireActual('react-redux'),
  useDispatch: jest.fn(),
}));

describe('CounterButton Component', () => {
  let mockDispatch;

  beforeEach(() => {
    // Reset the mock before each test
    mockDispatch = jest.fn();
    useDispatch.mockReturnValue(mockDispatch);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should dispatch the INCREMENT action when clicked', () => {
    render(<CounterButton />);

    // Find the button and trigger a click event
    const button = screen.getByRole('button', { name: /increment/i });
    fireEvent.click(button);

    // Assert that dispatch was called with the correct action object
    expect(mockDispatch).toHaveBeenCalledTimes(1);
    expect(mockDispatch).toHaveBeenCalledWith({ type: 'INCREMENT' });
  });
});

Key Takeaways