unit-testingtestingreduxredux-thunkredux-mock-store

Redux action testing with nock and redux-mock-store errors


I am new to redux testing and have been trying to back fill test for an application I made so sorry if this is the complete wrong way to go about testing with nock and redux-mock-store.

//Action in authAction.js
export function fetchMessage() {
  return function(dispatch) {
    axios.get(ROOT_URL, {
      headers: { authorization: localStorage.getItem('token') }
    })
      .then(response => {
        console.log("hi")
        dispatch({
          type: FETCH_MESSAGE,
          payload: response.data.message
        });
      })
      .catch(response => {
        console.log(response)
        //callingRefresh(response,"/feature",dispatch);
      });
  }
}

This is the method and it seems to be getting called but normally goes to the catch cause of nock failing cause of the header not matching.

//authActions_test.js
import nock from 'nock'
import React from 'react'
import {expect} from 'chai'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

const middlewares = [ thunk ]
const mockStore = configureMockStore(middlewares)

import * as actions from '../../src/actions/authActions';
const ROOT_URL = 'http://localhost:3090';

describe('actions', () => {

    beforeEach(() => {
        nock.disableNetConnect();
        localStorage.setItem("token", '12345');
    });

    afterEach(() => {
        nock.cleanAll();
        nock.enableNetConnect();
    });


  describe('feature', () => {

    it('has the correct type', () => {
      var scope = nock(ROOT_URL).get('/',{reqheaders: {'authorization': '12345'}}).reply(200,{ message: 'Super secret code is ABC123' });
      const store = mockStore({ message: '' });

      store.dispatch(actions.fetchMessage()).then(() => {
      const actions = store.getStore()
      expect(actions.message).toEqual('Super secret code is ABC123');
    })


    });
  });
});

Even when the header is removed and the nock intercepts the call. I am getting this error every time

TypeError: Cannot read property 'then' of undefined
  at Context.<anonymous> (test/actions/authActions_test.js:43:24)

Solution

  • You're not returning the promise from axios to chain the then call onto.

    Change the thunk to be like:

    //Action in authAction.js
    export function fetchMessage() {
      return function(dispatch) {
        return axios.get(ROOT_URL, {
          headers: { authorization: localStorage.getItem('token') }
        })
          .then(response => {
            console.log("hi")
            dispatch({
              type: FETCH_MESSAGE,
              payload: response.data.message
            });
          })
          .catch(response => {
            console.log(response)
            //callingRefresh(response,"/feature",dispatch);
          });
      }
    }
    

    You may also need to change the test so that it doesn't pass before the promise resolves. How to do this changes depending on which testing library you use. If you're using mocha, take a look at this answer.

    Side note: I'm not sure if you have other unit tests testing the action creator separately to the reducer, but this is a very integrated way to test these. One of the big advantages of Redux is how easily each seperate cog of the machine can be tested in isolation to each other.