Reputation: 1151
I have a module that looks like follows:
calculate-average.js
const fetch = require('node-fetch') const stats = require('stats-lite') const BASE_URL = 'https://www.example.com/api' const calculateAverage = async(numApiCalls) => { const importantData = [] for (let i = 0; i < numApiCalls; i++) { const url = `${BASE_URL}/${i}` // will make requests to https://www.example.com/api/0, https://www.example.com/api/1 and so on.... const res = await fetch(url) const jsonRes = await res.json() importantData.push(jsonRes.importantData) } return stats.mean(importantData) } module.exports = calculateAverage
I tried testing it along the following lines but I am clearly way off from the solution:
calculate-average.test.js
const calculateAverage = require('../calculate-average') jest.mock( 'node-fetch', () => { return jest.fn(() => {}) } ) test('Should calculate stats for liquidation open interest delatas', async() => { const stats = await calculateAverage(100) // Should make 100 API calls. console.log(stats) })
What I need to do is the following:
https://www.example.com/api/0
returns { importantData: 0 }
, a call to https://www.example.com/api/1
returns { importantData: 1 }
and so on...url
that I have not specified a response for, a default response is provided. For example if a response is made to https://www.example.com/api/101
, then a default response of { importantData: 1000 }
is sent.I would preferably like to do this only using Jest without depending on modules like mock-fetch
and jest-mock-fetch
. However, if the solution without using is way too complex, then I would be happy to use them. Just don't want to create unnecessary dependencies if not required.
Upvotes: 6
Views: 10752
Reputation: 6325
Sure you can! You can use mock function mockResolvedValueOnce
method to return a result for a specific call and mockResolvedValue
to return the default result.
jest.mock('node-fetch', () => {
const generateResponse = (value) => {
return { json: () => ({ importantData: value }) };
};
return jest
.fn()
.mockResolvedValue(generateResponse(1000)) // default response
.mockResolvedValueOnce(generateResponse(0)) // response for first call
.mockResolvedValueOnce(generateResponse(1)) // response for second call
.mockResolvedValueOnce(generateResponse(2)); // response for third call
});
Note that we are returning an object with the json
property so that it returns the json data when you call res.json()
in calculate-average.js
.
url
parameter, you will have to mock the desired behaviour in the returned mock function for node-fetch
. The following example will mock the returned value so that for URLs where the counter is greater than 100 it will return 1000. Otherwise, it will return the same value present in the url
:
jest.mock('node-fetch', () => {
return jest.fn((url) => {
// Get and parse the URL parameter.
const value = parseInt(url.split('/').slice(-1)[0], 10);
return Promise.resolve({
json: () => ({ importantData: value > 100 ? 1000 : value })
});
});
});
Upvotes: 4