How to Mock Redux Store in React
Testing React components that rely on a Redux store requires a way to
simulate state and actions. This article provides a straightforward
guide on how to mock a Redux store in React applications using popular
testing libraries like Jest, React Testing Library, and
redux-mock-store. You will learn the best practices for
setting up mock providers, simulating state changes, and testing
dispatched actions.
Method 1: Wrapping Components in a Real Store (Recommended)
The most reliable way to test components using Redux is to wrap them in a real Redux store preloaded with test data. This approach, recommended by the Redux team, ensures your tests behave exactly like your production application.
First, create a helper function in your test setup file to wrap your
components with a <Provider>:
import React from 'react';
import { render } from '@testing-library/react';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import userReducer from './userSlice'; // Your actual reducer
export function renderWithProviders(
ui,
{
preloadedState = {},
store = configureStore({ reducer: { user: userReducer }, preloadedState }),
...renderOptions
} = {}
) {
function Wrapper({ children }) {
return <Provider store={store}>{children}</Provider>;
}
return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) };
}You can then use this helper inside your test suites to pass a specific initial state:
test('renders user name from Redux store', () => {
const { getByText } = renderWithProviders(<UserProfile />, {
preloadedState: {
user: { name: 'John Doe' }
}
});
expect(getByText(/John Doe/i)).toBeInTheDocument();
});Method 2: Using the
redux-mock-store Library
If you need to inspect which actions were dispatched to the store
rather than testing state changes, the redux-mock-store
library is the ideal choice.
First, install the library:
npm install redux-mock-store --save-devNext, configure the mock store in your test file:
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import MyComponent from './MyComponent';
const mockStore = configureStore([]);
test('dispatches login action on button click', () => {
const initialState = { user: { loggedIn: false } };
const store = mockStore(initialState);
render(
<Provider store={store}>
<MyComponent />
</Provider>
);
fireEvent.click(screen.getByRole('button', { name: /log in/i }));
const actions = store.getActions();
expect(actions[0]).toEqual({ type: 'user/login' });
});Method 3: Mocking Redux Hooks with Jest
If you want to avoid wrapping your components with providers
entirely, you can mock the React Redux hooks (useSelector
and useDispatch) directly using Jest. This method is
lightweight and suitable for simple unit tests.
Here is how you can spy on and mock these hooks:
import React from 'react';
import { render, screen } from '@testing-library/react';
import * as reactRedux from 'react-redux';
import MyComponent from './MyComponent';
describe('MyComponent with Mocked Hooks', () => {
const useSelectorMock = jest.spyOn(reactRedux, 'useSelector');
const useDispatchMock = jest.spyOn(reactRedux, 'useDispatch');
beforeEach(() => {
useSelectorMock.mockClear();
useDispatchMock.mockClear();
});
test('displays correct user status', () => {
// Mock selector return value
useSelectorMock.mockReturnValue({ name: 'Jane Doe', role: 'Admin' });
// Mock dispatch function
const dummyDispatch = jest.fn();
useDispatchMock.mockReturnValue(dummyDispatch);
render(<MyComponent />);
expect(screen.getByText('Jane Doe')).toBeInTheDocument();
expect(screen.getByText('Admin')).toBeInTheDocument();
});
});