简体   繁体   中英

Mocking node-fetch with jest creating a Response Object for mocking

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 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM