I am trying to create Response Objects for mocking with jest, I can't seem to get the right syntax.
Initialization,
jest.mock('node-fetch')
const fetch = require('node-fetch')
const { Response, Headers } = jest.requireActual('node-fetch')
// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
const meta = {
'Content-Type': 'application/json',
'Accept': '*/*',
'Breaking-Bad': '<3'
}
// You can in fact use any iterable objects, like a Map or even another Headers
const headers = new Headers(meta)
const copyOfHeaders = new Headers(headers)
const ResponseInit = {
status: 200,
statusText: 'fail',
headers: headers
}
With a basic test
test('Basic Test', async () => {
const token = ''
const getDocList = new Response(JSON.stringify(downloadDocumentData), ResponseInit)
fetch.mockResolvedValueOnce(Promise.resolve(getDocList))
await module.doSomething('mock', token)
.then( async(res) => {
await expect(res.data).toEqual(Object)
})
}, 5000)
I'm getting an error which is
FetchError {
message:
'invalid json response body at reason: Unexpected token H in JSON at position 2',
type: 'invalid-json' }
How can I initial a response for valid json, I have tried a lot of different things.
Following the article at https://jestjs.io/docs/en/bypassing-module-mocks but I want to return and test json instead.
We have to mock both promises with jest. fn to get the same behavior: By doing this, when the function getPricesLastDays calls fetch, the mocked out version of fetch will be called. Thus, we have a predictable return.
When mocking global object methods in Jest, the optimal way to do so is using the jest. spyOn() method. It takes the object and name of the method you want to mock, and returns a mock function. The resulting mock function can then be chained to a mocked implementation or a mocked return value.
We should use jest.mock(moduleName, factory, options) to mock node-fetch
module and fetch
function.
In order to construct the response object of the fetch
function, you need to use the Response
class provided by the node-fetch
module, so use jest.requireActual(moduleName) to get the original, unmocked node-fetch
Module and Response
class.
Of course, we can construct the response object arbitrarily, but the instance of the Response
class is really close to the real response.
The same goes for headers
object.
Here is a working demo:
index.js
:
const fetch = require('node-fetch');
module.exports = {
async doSomething(url, token) {
return fetch(url).then(res => res.json());
}
};
index.spec.js
:
jest.mock('node-fetch');
const fetch = require('node-fetch');
const { Response, Headers } = jest.requireActual('node-fetch');
const mod = require('./');
const meta = {
'Content-Type': 'application/json',
Accept: '*/*',
'Breaking-Bad': '<3'
};
const headers = new Headers(meta);
const copyOfHeaders = new Headers(headers);
const ResponseInit = {
status: 200,
statusText: 'fail',
headers: headers
};
test('Basic Test', async () => {
const token = '';
const downloadDocumentData = { data: {} };
const getDocList = new Response(JSON.stringify(downloadDocumentData), ResponseInit);
fetch.mockResolvedValueOnce(Promise.resolve(getDocList));
const res = await mod.doSomething('mock', token);
expect(res).toEqual({ data: {} });
expect(fetch).toBeCalledWith('mock');
});
Unit test result:
PASS src/stackoverflow/58648691/index.spec.js
✓ Basic Test (5ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.557s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58648691
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