How to change the behaviour of a mocked import?

You can mock with a spy and import the mocked module. In your test you set how the mock should behave using mockImplementation:

jest.mock('the-package-to-mock', () => ({
  methodToMock: jest.fn()
}));
import { methodToMock } from 'the-package-to-mock'

it('test1', () => {
  methodToMock.mockImplementation(() => 'someValue')
})

it('test2', () => {
  methodToMock.mockImplementation(() => 'anotherValue')
})

I use the following pattern:

'use strict'

const packageToMock = require('../path')

jest.mock('../path')
jest.mock('../../../../../../lib/dmp.db')

beforeEach(() => {
  packageToMock.methodToMock.mockReset()
})

describe('test suite', () => {
  test('test1', () => {
    packageToMock.methodToMock.mockResolvedValue('some value')
    expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)

  })
  test('test2', () => {
    packageToMock.methodToMock.mockResolvedValue('another value')
    expect(theThingToTest.someAction().type).toBe(types.OTHER_TYPE)
  })
})

Explanation:

You mock the class you are trying to use on test suite level, make sure the mock is reset before each test and for every test you use mockResolveValue to describe what will be return when mock is returned


Another way is to use jest.doMock(moduleName, factory, options).

E.g.

the-package-to-mock.ts:

export function methodToMock() {
  return 'real type';
}

toTest.ts:

import { methodToMock } from './the-package-to-mock';

export function someAction() {
  return {
    type: methodToMock(),
  };
}

toTest.spec.ts:

describe('45006254', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  it('test1', () => {
    jest.doMock('./the-package-to-mock', () => ({
      methodToMock: jest.fn(() => 'type A'),
    }));
    const theThingToTest = require('./toTest');
    expect(theThingToTest.someAction().type).toBe('type A');
  });

  it('test2', () => {
    jest.doMock('./the-package-to-mock', () => ({
      methodToMock: jest.fn(() => 'type B'),
    }));
    const theThingToTest = require('./toTest');
    expect(theThingToTest.someAction().type).toBe('type B');
  });
});

unit test result:

 PASS  examples/45006254/toTest.spec.ts
  45006254
    ✓ test1 (2016 ms)
    ✓ test2 (1 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 toTest.ts |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.443 s

source code: https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/45006254


spyOn worked best for us. See previous answer:

https://stackoverflow.com/a/54361996/1708297