How to Mock Redux Selectors in React
Mocking Redux selectors is a crucial technique in React testing that
allows you to isolate components from the global Redux store. This
article explains how to mock Redux selectors in unit and integration
tests using Jest and React Testing Library. You will learn how to mock
the useSelector hook directly, mock individual selector
functions, and provide a mocked Redux store as an alternative best
practice.
Method 1: Mocking
useSelector Directly
The quickest way to mock a selector’s return value is by spying on
the useSelector hook from the react-redux
library. This is highly effective when you want to control what the hook
returns without worrying about the underlying store or selector
implementation.
import React from 'react';
import { render, screen } from '@testing-library/react';
import * as reactRedux from 'react-redux';
import { MyComponent } from './MyComponent';
// Spy on the useSelector hook
const useSelectorMock = jest.spyOn(reactRedux, 'useSelector');
describe('MyComponent', () => {
beforeEach(() => {
useSelectorMock.mockClear();
});
it('should render the mocked selector data', () => {
// Define what the selector should return for this test
useSelectorMock.mockReturnValue({ name: 'John Doe', isLoggedIn: true });
render(<MyComponent />);
expect(screen.getByText('Welcome, John Doe')).toBeInTheDocument();
});
});Method 2: Mocking Specific Selector Functions
If your component imports custom selector functions (such as those created with Reselect), you can mock the selector file directly using Jest. This approach is cleaner if your component uses multiple selectors, as it allows you to mock them individually.
Assume you have a selector file named selectors.js:
// selectors.js
export const selectUser = (state) => state.user;
export const selectIsLoading = (state) => state.ui.isLoading;You can mock these selectors in your test file like this:
import React from 'react';
import { render, screen } from '@testing-library/react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { MyComponent } from './MyComponent';
import * as selectors from './selectors';
// Mock the entire selector file
jest.mock('./selectors', () => ({
selectUser: jest.fn(),
selectIsLoading: jest.fn(),
}));
describe('MyComponent with Mocked Selectors', () => {
it('should render user data using mocked selectors', () => {
// Set specific return values for the mocked selectors
selectors.selectUser.mockReturnValue({ name: 'Jane Doe' });
selectors.selectIsLoading.mockReturnValue(false);
// We still need a wrapper Provider, but the actual state won't matter
const dummyStore = createStore(() => ({}));
render(
<Provider store={dummyStore}>
<MyComponent />
</Provider>
);
expect(screen.getByText('User: Jane Doe')).toBeInTheDocument();
});
});Method 3: Providing a Mocked Store (Recommended)
Instead of mocking mock-functions, the most robust testing practice
is to wrap your component in a real Redux <Provider>
populated with a mock state. This avoids mocking React Redux internals
and ensures your tests behave closer to how the application runs in
production.
You can create a helper render function to handle this setup:
import React from 'react';
import { render } from '@testing-library/react';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import { MyComponent } from './MyComponent';
import userReducer from './userSlice';
// Helper function to render components with a custom preloaded Redux state
function renderWithRedux(
ui,
{
preloadedState = {},
store = configureStore({ reducer: { user: userReducer }, preloadedState }),
} = {}
) {
return {
...render(<Provider store={store}>{ui}</Provider>),
store,
};
}
describe('MyComponent with Redux Wrapper', () => {
it('renders user info from the preloaded state', () => {
renderWithRedux(<MyComponent />, {
preloadedState: {
user: { name: 'Alice', isLoggedIn: true },
},
});
expect(screen.getByText('Welcome, Alice')).toBeInTheDocument();
});
});