1
function getusers(config){
     const {successCB} = config;
     return axios.get(url, params)
      .then(response => {
        successCB(response.data, config);
      });
}

************************ UT ******************************

const mock = new MockAdapter(axios);
const successCB = jest.fn();

mock.onGet(url).reply(200, 'success');
const axiosSpy = jest.spyOn(axios, 'get');
const successCBSpy = jest.spyOn(config, 'successCB');

getUsers({successCB});

axiosSpy is success from below code

expect(axiosSpy).toHaveBeenCalled();

But it's not reaching inside to resolve with results for successCB

expect(successCBSpy).toHaveBeenCalled();

Throwing error as: successCB never called

What am I doing wrong and what should I expect here?

I am only able to use ES6 solutions only.

halfer
  • 19,824
  • 17
  • 99
  • 186
Mithun Shreevatsa
  • 3,588
  • 9
  • 50
  • 95

1 Answers1

3

Make sure you return the Promise from getusers so you can await it in your test.

Here is a complete working example:

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

const url = 'test-url';
const params = {};

function getusers(config) {
  const { successCB } = config;
  return axios.get(url, params)  // <= return the Promise
    .then(response => {
      successCB(response.data, config);
    });
}

test('getusers', async () => {  // <= async test function
  const mock = new MockAdapter(axios);
  const successCB = jest.fn();

  mock.onGet(url).reply(200, 'success');
  const axiosSpy = jest.spyOn(axios, 'get');

  await getusers({ successCB });  // <= await the Promise

  expect(axiosSpy).toHaveBeenCalled();  // Success!
  expect(successCB.mock.calls[0][0]).toBe('success');  // Success!
})

Update

If async/await syntax is not an option then you can do the assertions in a then callback and return the resulting Promise from the test so Jest knows to wait for it:

test('getusers', () => {
  const mock = new MockAdapter(axios);
  const successCB = jest.fn();

  mock.onGet(url).reply(200, 'success');
  const axiosSpy = jest.spyOn(axios, 'get');

  return getusers({ successCB }).then(() => {
    expect(axiosSpy).toHaveBeenCalled();  // Success!
    expect(successCB.mock.calls[0][0]).toBe('success');  // Success!
  });
})
Brian Adams
  • 43,011
  • 9
  • 113
  • 111
  • now the successCB has been defined as jest.fn() in our code and our project is not supported with ES7. Any chance to resolve it using ES6 ? – Mithun Shreevatsa Mar 20 '19 at 11:09
  • 1
    @Mithun I just provided the general idea of what you need to do. If you update your question with your actual test code I'll update my answer based on the code you share – Brian Adams Mar 20 '19 at 11:11
  • @ brian-lives-outdoors - updated my question, please have a look – Mithun Shreevatsa Mar 20 '19 at 13:04
  • 1
    @Mithun I updated my answer with a complete working example – Brian Adams Mar 20 '19 at 13:23
  • async, await is not supported in our application @brian – Mithun Shreevatsa Mar 20 '19 at 13:26
  • `Promise { }` i see this as the promise not being resolved. I am wondering if there is a way to reolve the promise using spy in jest, similar functionality was present in jasmine karma when working with angular – Mithun Shreevatsa Mar 20 '19 at 13:30
  • 1
    @Mithun I added an example for testing without using `async/await` syntax – Brian Adams Mar 20 '19 at 13:31
  • Almost in the last phase, ill accept the answer. One last thing successCB is a callback function passed to getUsers. So, i am not able to expect the response result of `success` from `successCB`. Could you please tweak a little. Ill close this question – Mithun Shreevatsa Mar 20 '19 at 13:35
  • 1
    @Mithun I just add those comments as a way to indicate the test passes, but sure, I can remove them – Brian Adams Mar 20 '19 at 13:37
  • `expect(successCB).toHaveBeenCalledWith('success'); ` throws as error like `undefined` – Mithun Shreevatsa Mar 20 '19 at 13:41
  • 1
    @Mithun ah, I get what you are asking now. Remove `config` as the second argument to `successCB` in `getusers`. I've updated the code and tests in my answer – Brian Adams Mar 20 '19 at 13:46
  • I am sorry, we can't remove the second argument. `Comparing two different types of values. Expected string but received the object.` // its comparing `empty object {}` with `string success`. should we change the success callback implementation of mock.jest.fn() ? is what I am thinking – Mithun Shreevatsa Mar 20 '19 at 13:51
  • 1
    @Mithun k, then you can check **just the first argument** that the callback was called with by using [`mockFn.mock.calls`](https://jestjs.io/docs/en/mock-function-api#mockfnmockcalls). Answer updated. – Brian Adams Mar 20 '19 at 13:54
  • Brilliant, i learnt something new from you today, thanks @brian – Mithun Shreevatsa Mar 20 '19 at 13:58
  • 1
    @Mithun glad I was able to help! – Brian Adams Mar 20 '19 at 14:00