w3resource

Bypassing module mocks


Jest will allow you to mock out whole modules in your tests, which can be useful for testing if your code is calling functions from that module correctly. However, sometimes you may want to use parts of a mocked module in your test file, in which case you want to access the original implementation, rather than a mocked version.

Consider for example, when you are writing a test case for this createUser function:

// createUser.js

import fetch from 'node-fetch';

export const createUser = async () => {
  const response = await fetch('http://website.com/users', {method: 'POST'});
  const userId = await response.text();
  return userId;
};

Your test will want to mock the fetch function so that you can be sure that it will get called without actually making the network request. However, you will equally need to mock the return value of fetch with a Response (wrapped in a Promise), as our function will use it to grab the created user's ID. So you could initially try writing a test like this:

jest.mock('node-fetch');

import fetch, {Response} from 'node-fetch';

import {createUser} from './createUser';

test('createUser calls fetch with the right args and returns the user id', async () => {
  fetch.mockReturnValue(Promise.resolve(new Response('4')));

  const userId = await createUser();

  expect(fetch).toHaveBeenCalledTimes(1);
  expect(fetch).toHaveBeenCalledWith('http://website.com/users', {
    method: 'POST',
  });
  expect(userId).toBe('4');
});

However, if you run that test you will find that the createUser function will fail, throwing this error: TypeError: response.text is not a function. This happens because the Response class that you have imported from node-fetch has been mocked (due to the jest.mock call at the top of the test file) so that it no longer behaves the way it should.

If you want to get around problems such as this, Jest will provide the jest.requireActual helper. In order to make the above test work, you should make the following change to the imports in the test file:

// BEFORE

jest.mock('node-fetch');
import fetch, {Response} from 'node-fetch';

// AFTER

jest.mock('node-fetch');
import fetch from 'node-fetch';
const {Response} = jest.requireActual('node-fetch');

This will allow your test file to import the actual Response object from node-fetch, instead of a mocked version. This will mean the test will now pass correctly.



Inviting useful, relevant, well-written and unique guest posts