I am writing this post to show how to mock and test fetch with jest-fetch-mock. let's suppose that you are using Jest and you are comfortable with “async/await”.
In this post, we are going to test an application that is going to request information from:
https://us-central1-js-capstone-backend.cloudfunctions.net/api/games/
To make it possible, we have to mock our fetch.
Add necessary packages
Before starting, we have to install jest in our application throw this command:
npm add --dev jest.
Then, we have to add jest in our
package.json
like this:"scripts": {
"test": "jest",
},
Now we will be able to test our functions and class throw this command:
npm test.
Next, we have to add a jest-fetch-mock module in our application to mock our fetch.
So, type this command:
npm add --dev jest-fetch-mock.
Then, in our
package.json
add:"jest": {
"automock": false,
"setupFiles": ["./setupJest.js"]
},
Finally, create a
setupJest.js
file with this code global.fetch = require('jest-fetch-mock');
then put it in the root of your project.Now, we will be able to test our code without making requests to that the API every time we run tests.
Our API function looks like this:
const Api = (() => {
const key = 'FBPkKVVQVi1i5V71obYP';
const urlRequest = `https://us-central1-js-capstone-backend.cloudfunctions.net/api/games/${key}/scores`;
const getScores = () => new Promise((resolve, reject) => {
fetch(urlRequest)
.then(response => response.json()
.then((json) => {
resolve(json.result);
})).catch((e) => {
reject(e);
});
});
const setScores = (data) => fetch(urlRequest, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
}).then(result => result.json());
return { getScores, setScores };
})();
export default Api;
Writing the Tests:
let's put our API test file in a folder named test.
1. The first thing that we have to do is, to reset the fetch mock so, the previous tests don't interfere with the current test by adding this code in our test file:
import Api from '../controller/api';
beforeEach(() => {
fetch.resetMocks();
});
2. Now, lets test our
GET
method throw this code:it('Return score', async () => {
fetch.mockResponseOnce(JSON.stringify({
result: [
{
user: 'John Doe',
score: 42,
}],
}));
const res = await Api.getScores();
expect(res).toEqual([{ score: 42, user: 'John Doe' }]);
expect(fetch.mock.calls.length).toEqual(1);
});
In this test, we expect that our test will return an array with this value:
{ score: 42, user: 'John Doe' }.
Now, let's test our
method with this code:POST
test('Return value for POST action', () => {
fetch.mockResponseOnce(JSON.stringify([{ result: 'Leaderboard score created correctly.' }]));
const onResponse = jest.fn();
const onError = jest.fn();
return Api.setScores()
.then(onResponse)
.catch(onError)
.finally(() => {
expect(onResponse).toHaveBeenCalled();
expect(onError).not.toHaveBeenCalled();
expect(onResponse.mock.calls[0][0][0]).toEqual({ result: 'Leaderboard score created correctly.' });
});
});
Here, after sending our data, we expect that our API will return: { result: 'Leaderboard score created correctly.' }.
Now if you run the tests you'll see we're all green!
Also published on: https://medium.com/@josiarj/how-to-mock-fetch-in-jest-f662eaec6090