Ateev Chopra Ateev Chopra - 2 days ago 5
React JSX Question

Unit Testing redux async function

I'm pretty new to unit testing so please pardon any noobness.

I have a file

api.js
which has all the API call functions for the app. Each function returns its promise. Here's how it looks:

api.js

const api = {
getData() {
return superagent
.get(apiUrl)
.query({
page: 1,
});
},
}


Now coming to the redux async action that i'm trying to test. It looks something like this:

getDataAction.js

export function getData(){
return dispatch => {
api.getData()
.end((err, data) => {
if (err === null && data !== undefined) {
console.log(data);
} else if (typeof err.status !== 'undefined') {
throw new Error(`${err.status} Server response failed.`);
}
});
}
}


Now, In my test file, I've tried this:

getDataAction.test.js

jest.mock('api.js');
describe('getData Action', () => {
it('gets the data', () => {
expect(store.dispatch(getData())).toEqual(expectedAction);
});
});


This, throws me an error:

TypeError: Cannot read property 'end' of undefined


What am I doing wrong ? Now i'm able to mock api.js with default automocker of Jest, but how do I handle the case of running callback function with
end
? Thanks a lot for any help !

Answer

Your mock of api needs to return a function that returns an object that has the end function:

import api from 'api' //to set the implantation of getData we need to import the api into the test

// this will turn your api into an object with the getData function
// initial this is just a dumb spy but you can overwrite its behaviour in the test later on 
jest.mock('api.js', ()=> ({getData: jest.fn()}));

describe('getData Action', () => {
  it('gets the data', () => {
    const result = {test: 1234}
    // for the success case you mock getData so that it returns the end function that calls the callback without an error and some data
    api.getData.mockImplementation(() => ({end: cb => cb(null, result)}))
    expect(store.dispatch(getData())).toEqual(expectedAction);
  });

 it('it thows on error', () => {

    // for the error case you mock getData so that it returns the end function that calls the callback with an error and no data
    api.getData.mockImplementation(() => ({end: cb => cb({status: 'someError'}, null)}))
    expect(store.dispatch(getData())).toThrow();
  });
});
Comments