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); }