1
votes

I'm writing some units tests and need to mock a named export from a file, but it doesn't seem to work when the export is a function that returns a promise.

For example, I have a module located at lib/api.js that exports a single function called getFoo, which itself returns axios.get('/foo').

In my tests, I want to mock the return value of getFoo to be a resolved promise with the foo payload, so I mock using a module factory:

import * as api from 'lib/api';
jest.mock('lib/api', () => ({
  getFoo: jest.fn(() => Promise.resolve('foo')),
});

and then in my test I want to assert that getFoo was called as part of larger process of chained promises.

it('getBar should call getFoo', () => {
  return getBar().then(() => {
    expect(api.getFoo).toHaveBeenCalled();
  });
})

The error I get here is cannot read property 'then' of undefined, as though the jest function used in the mocked module factory is not returning the promise.

If the return value for getFoo is not a promise, it works as expected. If I use jest.fn() as the value for getFoo, and then in the test itself mock the implementation...

it('getBar should call getFoo', () => {
  api.getFoo.mockImplementation(() => Promise.resolve("foo"));
  return getBar().then(() => {
    expect(api.getFoo).toHaveBeenCalled();
  });
})

...then it works. My understanding is that the jest.fn(() => {}) should just be a shorter way of defining the implementation, so I am not sure why I am getting the error. Any help appreciated.

Thanks.

More Info:

The lib/api looks like this...

import axios from 'axios';

export const getFoo = (host: string, accessToken: string): Promise<{}> =>
  axios.get(`${host}/foo`, {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    }
  })
  // return foo
  .then((response) => response.data)
  .catch(() => {
    throw new Error('Failed to load foo');
  });

When I console log the mocked getFoo function while the test is running, it shows up as...

getFoo function mockConstructor() {
  return fn.apply(this, arguments);                                                                         }
1

1 Answers

0
votes

First thing, you need to mock it before importing it:

jest.mock('lib/api');

import * as api from 'lib/api';