Home > Software design >  How to mock some functions in a module with Jest
How to mock some functions in a module with Jest

Time:08-19

I have a module that only contains named exports.
I'm trying to test just two of the functions from that module - the cookieData function & the unauthenticate function.
I want the cookieData to be mocked unauthenticate remain un-mocked.

Here is a simplified view of what my module looks like index.js

const cookieData = () => {
    console.log('real cookieData fn hit')
}

const unauthenticate = () => {
    console.log('real unauthenticate fn hit')
    cookieData()
}

export { unauthenticate, cookieData }

I can successfully mock cookieData, if I call cookieData directly
(This is just to test that I've mocked cookieData properly)
unauthenticate.test.js

import { cookieData, unauthenticate } from '../src';

jest.mock('../src', () => {
  const original = jest.requireActual('../src');
  return {
    ...original,
    cookieData: jest.fn(() => console.log('fake cookieData fn hit'))
  };
});

test('error will be thrown if there is no cookie to be cleared', () => {
  cookieData();
  // The correct message "fake cookieData fn hit" is logged to the console
});

But, when I go to call unauthenticate from the test instead, my mock suddenly stops working and the real functions get hit.

import { cookieData, unauthenticate } from '../src';

jest.mock('../src', () => {
  const original = jest.requireActual('../src');
  return {
    ...original,
    cookieData: jest.fn(() => console.log('fake cookieData fn hit'))
  };
});

test('error will be thrown if there is no cookie to be cleared', () => {
  unauthenticate();
  // The wrong messages are logged to the console
  // This logs out "real unauthenticate fn hit" then "real cookieData fn hit"
  // It SHOULD be "real unauthenticate fn hit" then "fake cookieData fn hit"
});

I can't understand why my mock stops working when I use the unmocked function. I have also tried doing import * as module from '../src' and then just assigning an individual mock function to module.cookieData like this

module.cookieData = jest.fn(() => console.log('fake hit')); 

But that does not work either. When I call module.unathenticate() it will still call the real methods.

CodePudding user response:

What if you add __esModule: true, and try with the same code?

jest.mock('../src', () => {
  const original = jest.requireActual('../src');
  return {
    __esModule: true,
    ...original,
    cookieData: jest.fn(() => console.log('fake cookieData fn hit'))
  };
});

Basically this is how it is shown in the documentation

CodePudding user response:

The solution or work around was to modify how cookieData was used in the index file.

import * as module from './index';

const cookieData = () => {
    console.log('real cookieData fn hit')
}

const unauthenticate = () => {
    console.log('real unauthenticate fn hit')
    module.cookieData()
}

export { unauthenticate, cookieData }

Test file

import { cookieData, unauthenticate } from '../src';

jest.mock('../src', () => {
  const original = jest.requireActual('../src');
  return {
    ...original,
    cookieData: jest.fn(() => console.log('fake cookieData fn hit'))
  };
});

test('error will be thrown if there is no cookie to be cleared', () => {
  unauthenticate();
  // It logs out "real unauthenticate fn hit" then "fake cookieData fn hit"
});
  • Related