I'm trying to unit test a function using Jest, and I'm having some trouble dealing with jest mock modules (the equivalent of rewire or proxyquire in nodejs world).
I'm actually trying to test that a spy has been called on the mocked module with some parameters. Here's the function that I want to test.
NB : the current test only concerns the "fetch(...)" part, I m trying to test that fetch has been called with the good parameter.
export const fetchRemote = slug => {
return dispatch => {
dispatch(loading());
return fetch(Constants.URL + slug)
.then(res => res.json())
.then(cmp => {
if (cmp.length === 1) {
return dispatch(setCurrent(cmp[0]));
}
return dispatch(computeRemote(cmp));
});
};
};
The function returned acts as a closure, and so "captures" the node-fetch external module that I want to mock.
Here's the test I m trying to make pass green :
it('should have called the fetch function wih the good const parameter and slug', done => {
const slug = 'slug';
const spy = jasmine.createSpy();
const stubDispatch = () => Promise.resolve({json: () => []});
jest.mock('node-fetch', () => spy);
const dispatcher = fetchRemote(slug);
dispatcher(stubDispatch).then(() => {
expect(spy).toHaveBeenCalledWith(Constants.URL + slug);
done();
});
});
EDIT : The first answer helped a lot concerning writing the test, I have now the following one :
it('should have called the fetch function wih the good const parameter and slug', done => {
const slug = 'slug';
const stubDispatch = () => null;
const spy = jest.mock('node-fetch', () => Promise.resolve({json: () => []}));
const dispatcher = fetchRemote(slug);
dispatcher(stubDispatch).then(() => {
expect(spy).toHaveBeenCalledWith(Constants.URL + slug);
done();
});
});
But now, here's the error I have :
console.error node_modules/core-js/modules/es6.promise.js:117
Unhandled promise rejection [Error: expect(jest.fn())[.not].toHaveBeenCalledWith()
jest.fn() value must be a mock function or spy.
Received:
object: {"addMatchers": [Function anonymous], "autoMockOff": [Function anonymous], "autoMockOn": [Function anonymous], "clearAllMocks": [Function anonymous], "clearAllTimers": [Function anonymous], "deepUnmock": [Function anonymous], "disableAutomock": [Function anonymous], "doMock": [Function anonymous], "dontMock": [Function anonymous], "enableAutomock": [Function anonymous], "fn": [Function anonymous], "genMockFn": [Function bound getMockFunction], "genMockFromModule": [Function anonymous], "genMockFunction": [Function bound getMockFunction], "isMockFunction": [Function isMockFunction], "mock": [Function anonymous], "resetModuleRegistry": [Function anonymous], "resetModules": [Function anonymous], "runAllImmediates": [Function anonymous], "runAllTicks": [Function anonymous], "runAllTimers": [Function anonymous], "runOnlyPendingTimers": [Function anonymous], "runTimersToTime": [Function anonymous], "setMock": [Function anonymous], "unmock": [Function anonymous], "useFakeTimers": [Function anonymous], "useRealTimers": [Function anonymous]}]
In order to mock asynchronous code in Jest, more specifically Promises, you can use the mockResolvedValue function. This will mock the return value of the Promise to be 42. In order to test a Promise in Jest, you need to turn your it block into async in order to use the await keyword in front of an expect statement.
Try-catch with async/await (bad) It looks like using try-catch with async/await is the easiest way to achieve this as the rejected value is thrown: it("rejects (bad)", async () => { try { await promiseMe("Error"); } catch (e) { expect(e). toEqual("Error"); } }); But wait.
Use jest. mock() and post. mockImplementation() will do this. You can get the actual callback function passed in post function in your test case.
Mocking Modules export default Users; Now, in order to test this method without actually hitting the API (and thus creating slow and fragile tests), we can use the jest. mock(...) function to automatically mock the axios module.
In short, 3 simple steps to mock promise using Jest. Import the desired mock js module into your test file using require (). Using jest.mock ('js-filepath') to enable you to setup mocking for all functions within that module.
When you run jest.mock ('axios'), Jest replaces every function in the axios module with empty "mock" functions. These mock functions essentially do nothing and return undefined:
To mock an API call in a function, you just need to do these 3 steps: Import the module you want to mock into your test file. jest.mock () the module. Use .mockResolvedValue (<mocked response>) to mock the response.
We can use mockResolvedValue () in order to mock promise that is fulfilled and returning value. While for mocking promise that is rejected, we can use mockRejectedValue (). Refer to the example test below for more details.
First of all you need to return a promise when testing async code. And your spy needs to return a resolved or rejected promise.
it('should have called the fetch function wih the good const parameter and slug', done => {
const slug = 'successPath';
const stubDispatch = () => Promise.resolve({ json: () => [] });
spy = jest.mock('node-fetch', (path) => {
if (path === Constants.URL + 'successPath') {
return Promise.resolve('someSuccessData ')
} else {
return Promise.reject('someErrorData')
}
});
const dispatcher = fetchRemote(slug);
return dispatcher(stubDispatch).then(() => {
expect(spy).toHaveBeenCalledWith(Constants.URL + slug);
done();
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With