mock a function which is used in another function

698 Views Asked by At

I am writing test for my async action in react redux, for sake of addressing just the issue I simplified the code here. Here is my action function:

export function updateUserAuthenticationStatus(){
return function(dispatch){
   return axios.get(getLoginStatusUrl())
        .then(response => {
               const middlewares = [thunk];
               const mockStore = configureMockStore(middlewares);
               const store = mockStore();
    return store.dispatch(updateUserAuthenticationStatus()).then(()=>{
       //expect(store.getActions()[0]).to.eql(expectedActions);
    });
            });
        }).catch(function(response){
    });
  }
}

So the problem is the function getLoginStatusUrl() which does couple of checks in the cookie and return the appropriate url based on some conditions. So what I want is to mock this function to return for example test.com then I can test my action as follows:

it("", () => {
        **here I want to mock getLoginStatusUrl() to return test.com**
    nock("test.com")
        .get("/")
        .reply(200,"test detail");

})

How can I mock the getLoginStatusUrl() to return test.com in this scenario?

2

There are 2 best solutions below

4
Martin Dawson On

You don't need it to return test.com specifically. Use a library such as axios-mock-adapter. I haven't used it personaly but I'v used fetch-mock to mock fetch api requests so that concept should be exactly the same.

Lets say getLoginStatusUrl() returns /loginStatus, (because you haven't shown what it does return).

Example:

var axios = require('axios');
var MockAdapter = require('axios-mock-adapter');

// This sets the mock adapter on the default instance
var mock = new MockAdapter(axios);

// Mock any GET request to /users
// arguments for reply are (status, data, headers)
mock.onGet('/loginStatus').reply(200, {
  loginSuccess: true
});

axios.get('/loginStatus')
  .then(function(response) {
    console.log(response.data);
  });

The example code is untested but hopefuly you get the idea. Just read the library README.md.

In scenario's where you want to stub/mock out private imports that aren't used in axios requests like this you can use rewire or babel-plugin-rewire if you are using es6 syntax such as imports.

@HamedMinaee If you do not know the path at all, you can just do something like onGet('/'), it's all in the README.md. after the test I imagine their is a way to reset this so that not all tests using axios are affected by it.

afterEach(() => {
    // reset the axios mock here so that '/' doesn't affect all requests or something.
});
8
Ravindra Ranwala On

Try this out with sinon.

import {getLoginStatusUrl} from './some/path.js'

let stub = sinon.stub(),
opts = { call: getLoginStatusUrl() };

stub.withExactArgs().returns("somePredefinedReturnValue")