How to mock imported named function in Jest when module is unmocked

Solution 1:

Use jest.requireActual() inside jest.mock()

jest.requireActual(moduleName)

Returns the actual module instead of a mock, bypassing all checks on whether the module should receive a mock implementation or not.

Example

I prefer this concise usage where you require and spread within the returned object:

// myModule.test.js

import { otherFn } from './myModule.js'

jest.mock('./myModule.js', () => ({
  ...(jest.requireActual('./myModule.js')),
  otherFn: jest.fn()
}))

describe('test category', () => {
  it('tests something about otherFn', () => {
    otherFn.mockReturnValue('foo')
    expect(otherFn()).toBe('foo')
  })
})

This method is also referenced in Jest's Manual Mocks documentation (near the end of Examples):

To ensure that a manual mock and its real implementation stay in sync, it might be useful to require the real module using jest.requireActual(moduleName) in your manual mock and amending it with mock functions before exporting it.

Solution 2:

Looks like I'm late to this party, but yes, this is possible.

testFn just needs to call otherFn using the module.

If testFn uses the module to call otherFn then the module export for otherFn can be mocked and testFn will call the mock.


Here is a working example:

myModule.js

import * as myModule from './myModule';  // import myModule into itself

export function otherFn() {
  return 'original value';
}

export function testFn() {
  const result = myModule.otherFn();  // call otherFn using the module

  // do other things

  return result;
}

myModule.test.js

import * as myModule from './myModule';

describe('test category', () => {
  it('tests something about testFn', () => {
    const mock = jest.spyOn(myModule, 'otherFn');  // spy on otherFn
    mock.mockReturnValue('mocked value');  // mock the return value

    expect(myModule.testFn()).toBe('mocked value');  // SUCCESS

    mock.mockRestore();  // restore otherFn
  });
});

Solution 3:

import m from '../myModule';

Does not works for me, I did use:

import * as m from '../myModule';

m.otherFn = jest.fn();