Search code examples
reactjsreduxmocha.jsaxiosnock

Testing an HTTP post Request with mocha using nock


I'm learning how to test a frontend webapp without any connection to the API. My problem is: I have to test an POST HTTP Request but always get an error : TypeError: loginUser(...).then is not a function.

I know my expect is not correct. I must change the data for a JWT token, and also don't know yet hot to do it.

It's a simple user authentication. Http post sending an email and password, getting back a JWT (json web token). I have to write a test to make sure I've send the correct information and get a JWT as response.

Thanks for your help

Here is my code:

//login.test.js

const expect = require('chai').expect;
const loginUser = require('../src/actions/authActions').loginUser;
const res = require('./response/loginResponse');
const nock = require('nock');
const userData = {
   email: '[email protected]',
   password: '123456'
};

describe('Post loginUser', () => {
beforeEach(() => {
  nock('http://localhost:3000')
    .post('/api/users/login', userData )
    .reply(200, res);
});

it('Post email/pwd to get a token', () => {
    return loginUser(userData)
      .then(res => {
        //expect an object back
        expect(typeof res).to.equal('object');

        //Test result of name, company and location for the response
        expect(res.email).to.equal('[email protected]')
        expect(res.name).to.equal('Tralala!!!')
      });
  });
});


//authActions.js
import axios from "axios";
import setAuthToken from "../utils/setAuthToken";
import jwt_decode from "jwt-decode";
import {
  GET_ERRORS,
  SET_CURRENT_USER,
  USER_LOADING
} from "./types";

// Login - get user token
export const loginUser = userData => dispatch => {
axios
  .post("/api/users/login", userData)
  .then(res => {
    // Save to localStorage
    // Set token to localStorage
    const { token } = res.data;
    localStorage.setItem("jwtToken", token);
    // Set token to Auth header
    setAuthToken(token);
    // Decode token to get user data
    const decoded = jwt_decode(token);
    // Set current user
    dispatch(setCurrentUser(decoded));
  })
  .catch(err =>
    dispatch({
      type: GET_ERRORS,
      payload: err.response.data
    })
  );


// loginResponse.js
module.exports = { email: '[email protected]',
password: '123456',
name: "Tralala!!!"
};

Actual result: 1) Post loginUser Post email/pwd to get a token: TypeError: loginUser(...).then is not a function at Context.then (test/login.test.js:37:12)


Solution

  • The way you called loginUser method is not correct. This method returns another function. So, instead of loginUser(userData), you must also specify the dispatch parameter e.g. loginUser(userData)(dispatch).then().

    I changed the method to specify return before axios statement

    export const loginUser = userData => dispatch => {
      return axios // adding return
        .post("/api/users/login", userData)
        .then(res => {
         ...
        })
        .catch(err =>
          dispatch({
            type: GET_ERRORS,
            payload: err.response.data
          })
        );
    };
    

    for test, I may involve Sinon to spy the dispatch

    it("Post email/pwd to get a token", () => {
      const dispatchSpy = sinon.spy();
    
      return loginUser(userData)(dispatchSpy).then(res => {
        //expect an object back
        expect(typeof res).to.equal("object");
    
        //Test result of name, company and location for the response
        expect(res.email).to.equal("[email protected]");
        expect(res.name).to.equal("Tralala!!!");
      });
    });
    

    Hope it helps