React Redux Unit Testing


💡 To Test Redux, First, we have to mock the store. And to mock store, we will use a package named ‘redux-mock-store’.

You can find the package on this link:
https://www.npmjs.com/package/redux-mock-store

  > npm install redux-mock-store


💡 Let’s configure mock store –

import configureMockStore from 'redux-mock-store';
const mockStore = configureMockStore();
const store = mockStore();


💡 If you have thunk middleware then We have to pass middleware into our store like below code.

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

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


💡 If there are async actions means you are hitting an API call from your actions then You also need to mock Axios as well.

import axios from 'axios';
jest.mock('axios');

Action File – users.action.js

import axios from 'axios';

import { GET_USERS_REQUEST, GET_USERS_SUCCESS, GET_USERS_FAILURE } from './action-types';

export const GetUsers = () => (dispatch) => {
    dispatch(getUsersRequest());
    axios
      .get('https://jsonplaceholder.typicode.com/users')
      .then((response) => {
        const users = response.data;
        dispatch(getUsersSuccess(users));
      })
      .catch((error) => {
        dispatch(getUsersFailure(error.message));
      });
};

export const getUsersRequest = () => {
  return {
    type: GET_USERS_REQUEST,
  };
};

export const getUsersSuccess = (users) => {
  return {
    type: GET_USERS_SUCCESS,
    payload: users,
  };
};

export const getUsersFailure = (error) => {
  return {
    type: GET_USERS_FAILURE,
    payload: error,
  };
};

Unit Testing of the above Action file – users.action.test.js

import * as usersActions from './users.action';
import { GET_USERS_REQUEST, GET_USERS_SUCCESS } from './action-types';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

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

import axios from 'axios';
jest.mock('axios');

describe('UserActions', () => {
    beforeEach(() => {
        store.clearActions();
    });

    // Simple action testing that only have type
    test('should create an action to get User request', () => {
        const expectedAction = {
            type: GET_USERS_REQUEST
        }
        expect(usersActions.getUsersRequest()).toEqual(expectedAction);
    });

    // Action that have type and payload
    test('should create an action to get User Success', () => {
        const expectedAction = {
            type: GET_USERS_SUCCESS,
            payload: 'JsMount'
        }
        expect(usersActions.getUsersSuccess('JsMount')).toEqual(expectedAction);
    });

    // Testing of Async Action with Middleware
    test('should create an action to get Users List', async () => {
        const data = {
            data: [
                { name: 'JsMount', email: 'info@jsmount.com' },
                { name: 'web', email: 'technical@gmail.com' }
            ]
        }
        axios.get.mockImplementationOnce(() => Promise.resolve(data));
        await store.dispatch(usersActions.GetUsers());
        const actions = store.getActions();
        // console.log('actions :', actions);
        expect(actions[0].type).toEqual(GET_USERS_REQUEST);
        expect(actions[1].payload).toEqual(data.data);
    });
})

Reducer file – user-list.reducer.js


If you will see, you can find that the Reducer file contains only JavaScript functions. So there are no extra efforts to write test cases of reducers. You have to simply test JavaScript functions.

import { GET_USERS_REQUEST, GET_USERS_SUCCESS, GET_USERS_FAILURE } from '../actions/action-types';

const initialState = {
  loading: false,
  users: [],
  error: '',
};

const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case GET_USERS_REQUEST:
      return {
        ...state,
        loading: true,
      };
    case GET_USERS_SUCCESS:
      return {
        loading: false,
        users: action.payload,
        error: '',
      };
    case GET_USERS_FAILURE:
      return {
        loading: false,
        users: [],
        error: action.payload,
      };
    default:
      return state;
  }
};

export default userReducer;

React Redux Unit Testing

Unit testing of Reducers – user-list.reducer.test.js

import { GET_USERS_REQUEST, GET_USERS_SUCCESS } from '../actions/action-types';
import userReducer from './user-list.reducer';

describe('UserReducers', () => {
    it('should return initial state', () => {
        expect(userReducer(null, {})).toBe(null);
    })
    it('should handle GET_USERS_REQUEST', () => {
        const state = userReducer(undefined, { type: GET_USERS_REQUEST });
        expect(state.loading).toBeTruthy();
    })
    it('should handle GET_USERS_SUCCESS', () => {
        const state = userReducer(undefined, { type: GET_USERS_SUCCESS, payload: [{ name: 'test' }] });
        expect(state.loading).toBeFalsy();
        expect(state.users).toEqual([{ name: 'test' }]);
    })
});

Unit test case of useDispatch & useSelector

import React from 'react';
import * as redux from 'react-redux';
import {render, screen} from '@testing-library/react';
import UsersListWithSelector from './UserListWithUseSelector';

describe('User List testcases that contain useSelector & useDispatch', () => {
    let spyOnUseSelector;
    let spyOnUseDispatch;
    let mockDispatch;
    beforeEach(() => {
        spyOnUseSelector = jest.spyOn(redux, 'useSelector');
        // if you have to test other selectors then this line you can write on particular test case.
        spyOnUseSelector.mockReturnValue({users: [{ id: 1, name: 'John', email: 'username@gmail.com' }]});
        spyOnUseDispatch = jest.spyOn(redux, 'useDispatch');
        mockDispatch = jest.fn();
        spyOnUseDispatch.mockReturnValue(mockDispatch);
    });
    afterEach(() => {
        jest.restoreAllMocks();
      });
    it('render component', () => {
        render(<UsersListWithSelector/>);
        expect(screen.getByText('How to Build an Application Using React Js and Redux')).toBeInTheDocument();
    })
});

✔ React JS Interview Questions & Answers 2022 – Part 3

✔ Top React JS Interview Questions and Answers – Part 2

✔ React JS Interview Questions & Answers – Part 1

✔ Higher Order Component with Functional Component | React JS

✔ Create Custom QR Code Component using QR Code Styling in React JS

✔ React JS Stripe Payment Gateway Integration with Node | Step by Step Guide

✔ How to create a common Helper class or util file in React JS

✔ React Build Routing with Fixed Header and Navigation | React Router Tutorial

✔ React Create Dashboard Layout with Side Menu, Header & Content Area

Leave a Reply

Your email address will not be published.