Testing Redux-related code in Jest requires mocking store and actions:
1. Testing Redux Actions:
javascript// actions.js export const increment = () => ({ type: 'INCREMENT' }); export const addValue = (value) => ({ type: 'ADD_VALUE', payload: value }); // actions.test.js import { increment, addValue } from './actions'; describe('Actions', () => { test('creates increment action', () => { expect(increment()).toEqual({ type: 'INCREMENT' }); }); test('creates add value action', () => { expect(addValue(5)).toEqual({ type: 'ADD_VALUE', payload: 5 }); }); });
2. Testing Redux Reducers:
javascript// reducer.js const initialState = { count: 0 }; export default function counterReducer(state = initialState, action) { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'ADD_VALUE': return { count: state.count + action.payload }; default: return state; } } // reducer.test.js import counterReducer from './reducer'; describe('Counter Reducer', () => { test('returns initial state', () => { expect(counterReducer(undefined, {})).toEqual({ count: 0 }); }); test('handles INCREMENT', () => { const state = counterReducer({ count: 0 }, { type: 'INCREMENT' }); expect(state).toEqual({ count: 1 }); }); });
3. Testing Redux Selectors:
javascript// selectors.js export const selectCount = (state) => state.counter.count; // selectors.test.js import { selectCount } from './selectors'; test('selects count from state', () => { const state = { counter: { count: 5 } }; expect(selectCount(state)).toBe(5); });
4. Testing Redux Thunks:
javascript// thunks.js export const fetchUser = (id) => async (dispatch) => { const response = await fetch(`/api/users/${id}`); const user = await response.json(); dispatch({ type: 'FETCH_USER_SUCCESS', payload: user }); }; // thunks.test.js import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { fetchUser } from './thunks'; const mockStore = configureMockStore([thunk]); test('fetches user successfully', async () => { global.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve({ id: 1, name: 'John' }) }) ); const expectedActions = [ { type: 'FETCH_USER_SUCCESS', payload: { id: 1, name: 'John' } } ]; const store = mockStore({}); await store.dispatch(fetchUser(1)); expect(store.getActions()).toEqual(expectedActions); });
5. Testing React-Redux Components:
javascriptimport { render, screen } from '@testing-library/react'; import { Provider } from 'react-redux'; import Counter from './Counter'; import { createStore } from 'redux'; import reducer from './reducer'; test('renders counter with initial state', () => { const store = createStore(reducer); render( <Provider store={store}> <Counter /> </Provider> ); expect(screen.getByText('Count: 0')).toBeInTheDocument(); });
Best Practices:
- Test actions, reducers, and selectors separately
- Use
redux-mock-storeto test async actions - Mock API calls to isolate tests
- Provide mock store when testing components
- Keep tests simple and independent
- Avoid testing Redux internal implementation details