How to test your http requests for actions in React Redux

How to test your http requests for actions in React Redux

Another name for this post would be: How to test async store.dispatch react redux actions.

Seems like there is a lot of confusion about this topic, so I would show you how easy is to test that kind of actions using JEST, the important thing here is to not forget including in your expectations the param “done” if you forget it you will see always green tests because it is not really executing the async actions basically I’m talking about this format:

describe('yourFile', () => {

  it('your action', (done) => {
    store.dispatch(yourAction()).then(() => {
      //your expectations goes here
      done();
    })
  });
});

Let’s continue with an example.

My users actions look as follow:

export function getUserLoaderStart() {
  return {
    type: 'GET_USER_LOADER_START'
  }
}

export function getUserSuccess(users) {
  return {
    type: 'GET_USER_SUCCESS',
    users: users
  };
}

export function getUsersStart() {
  return function (dispatch, getState) {
    dispatch(getUserLoaderStart());

    // Make an HTTP Request
    return MyService.get('/users')
      .then(response => {
        let users = response.body.response;
        dispatch(getUserSuccess(users));
      })
      .catch(response => dispatch(errorFn(response)));
  };
}

MyService.js look as follow:

import superagentPromise from 'superagent-promise';
let request = superagentPromise(superagent, Promise);

const HOST_API_V1 = "localhost:3000/api/v1";
export default {
  get: (path, headers = {}) => {
    return request.get(HOST_API_V1 + path).set(headers).end();
  }
};

And this is the example and how to test it

import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk";
import Promise from "bluebird";

// include your service
import MyService from "../../src/services/MyService";
  
import {
  getUsersStart,
} from "../../src/actions/users";

describe('MyServiceActions', () => {
  let middlewares;
  let mockStore;
  let store;
  beforeEach(() => {
    middlewares = [thunk];
    mockStore = configureMockStore(middlewares);
    store = mockStore({
    });
  });

  it('getUsersStart returns an array of users and invoke some specific actions', (done) => {
    const response = {
      body: {
        response: [
          {
            id: '1',
            name: 'heriberto perez'
          }
        ]
      }
    };

    // you can also listen for changes in the store
    //store.subscribe(function() {
      //console.log(store.getState());
      //done();
    //});

    MyService.get = () => {
      return new Promise((resolve, reject) => {
        resolve(response);
      });
    }

    store.dispatch(getUsersStart()).then(() => {
      const arrayOfActions = store.getActions();
      expect(arrayOfActions[0]).toHaveProperty('type');
      expect(arrayOfActions[0]['type']).toEqual('GET_USER_LOADER_START');
      expect(arrayOfActions[1]).toHaveProperty('users');
      expect(arrayOfActions[1]['type']).toEqual('GET_USER_SUCCESS');
      expect(arrayOfActions.length).toEqual(2)
      done();
    })
  });
});

LAST NOTE: remember that `done` should be present when testing async http requests and when you’re testing simple actions remember to not use it cause it will behave funny :).

That’s it guys, hope you find it helpful and as always keep reading, coding and relax.

No Comments

Post A Comment