Ken Rosaka
Ken Rosaka

Reputation: 639

How to restore a mock created with jest.mock()?

Apparently mock.mockRestore() does not restore the original implementation of a mock created using jest.mock()

// a.js
export default class A {}


// b.js
import A from './a';
export default class B extends A {}


// test.js
import A from './a';
import B from './b';

jest.mock('./a');
jest.mock('./b');

const b = new B();

test('instanceOf', () => {
    A.mockRestore();
    B.mockRestore();
    expect(b).toBeInstanceOf(A); // fails
});

Upvotes: 38

Views: 38299

Answers (2)

Dmitri R117
Dmitri R117

Reputation: 2822

Assuming you cant use spyOn, you can do something like this:

// test.js

jest.mock('./a');
import A from './a';

A.mockImplementation(params => 'mockVal');
const actualA = jest.requireActual('./a');

test('instanceOf', () => {
    A.mockRestore(); // acts like mockReset()
    A.mockImplementation((params) => {
        return actualA(params);
    });
});

Upvotes: 1

Brian Adams
Brian Adams

Reputation: 45780

mockFn.mockRestore only works for a mock function created with jest.spyOn:

const obj = {
  func: () => 'original'
}

test('func', () => {
  const mock = jest.spyOn(obj, 'func');
  mock.mockReturnValue('mocked');

  expect(obj.func()).toBe('mocked');  // Success!

  mock.mockRestore();
  expect(obj.func()).toBe('original');  // Success!
})

jest.spyOn wraps the original function and provides mockRestore as a way to restore the original function.


jest.mock calls work a little differently.

Jest takes over the require system and jest.mock tells Jest that it should return the module mock instead of the actual module whenever it is required.

This means that the module mock doesn't wrap the original module, it completely replaces the original module in the require system. So mockRestore may be defined on mock functions within the module mock, but calling it doesn't restore the original implementation.


jest.mock is typically used when you want to mock an entire module for the whole test.

It is particularly useful when using ES6-style import statements since babel-jest hoists jest.mock calls and they run before anything else in the test file (including any import statements):

import A from './a';  // <= A is already mocked...

jest.mock('./a');  // <= ...because this runs first

test('A', () => {
  // ...
}

There isn't an easy way to restore the original module during a test that uses jest.mock since its primary use is to mock a module for an entire test.

If you are trying to use both a mock and the original implementation during the same test there are a few options:

  • Mock one particular function using jest.spyOn and restore it using mockRestore
  • Use jest.doMock to avoid the hoisting behavior of jest.mock...just note you also need to use require within the scope that uses jest.doMock instead of using a top-level import
  • Use jest.requireActual at any time to require the original module

Upvotes: 56

Related Questions