How to Mock Redux Middleware in React

Mocking Redux middleware in React is a crucial technique for isolating your components and action creators during unit testing. By replacing real middleware—such as Redux Thunk, Redux Saga, or custom logging middleware—with mocks, you can assert that specific actions are dispatched and side effects are triggered without executing actual API calls or complex asynchronous workflows. This article demonstrates how to mock Redux middleware using the popular redux-mock-store library and Jest spy functions.

Why Mock Redux Middleware?

In a production React application, Redux middleware handles side effects like asynchronous data fetching, logging, and routing. When writing unit tests for your components or action creators, running actual middleware can make tests slow, unpredictable, and dependent on external services. Mocking middleware allows you to:

Method 1: Using redux-mock-store

The most common way to mock Redux middleware is by using the redux-mock-store library. This library allows you to create a mock Redux store configured with your actual middleware (like redux-thunk) while intercepting dispatched actions for assertion.

First, install the library:

npm install redux-mock-store --save-dev

Next, configure the mock store with your middleware in your test file:

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { fetchUserData } from './actions';

const middleware = [thunk];
const mockStore = configureMockStore(middleware);

describe('Mocking Redux Thunk Middleware', () => {
  it('should dispatch the correct actions on API success', async () => {
    // Arrange: Create a mock store with initial state
    const store = mockStore({ user: {} });

    // Act: Dispatch an asynchronous action creator (thunk)
    await store.dispatch(fetchUserData());

    // Assert: Check the exact actions dispatched to the store
    const actions = store.getActions();
    expect(actions[0].type).toEqual('FETCH_USER_REQUEST');
    expect(actions[1].type).toEqual('FETCH_USER_SUCCESS');
  });
});

Method 2: Mocking Custom Middleware with Jest

If you have written a custom Redux middleware and want to test that it behaves correctly under certain conditions, you can mock the middleware’s curried function signature using Jest.

Redux middleware follows a specific triple-curried function pattern: store => next => action. Here is how you can mock and spy on this structure using Jest:

const createMockMiddleware = () => {
  const next = jest.fn();
  const store = {
    getState: jest.fn(() => ({})),
    dispatch: jest.fn(),
  };
  
  return { store, next };
};

describe('Custom Middleware Testing', () => {
  it('should pass the action to the next middleware', () => {
    const { store, next } = createMockMiddleware();
    
    // Your custom middleware
    const myCustomMiddleware = store => next => action => {
      return next(action);
    };

    const action = { type: 'TEST_ACTION' };
    
    // Execute the middleware chain
    myCustomMiddleware(store)(next)(action);

    // Verify that "next" was called with the correct action
    expect(next).toHaveBeenCalledWith(action);
  });
});

Using these two approaches, you can easily control the behavior of both third-party and custom Redux middleware, ensuring your React components and Redux logic are thoroughly tested in isolation.