Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
});
like image 552
Ken Rosaka Avatar asked Jun 07 '19 15:06

Ken Rosaka


People also ask

Is useful when you want to completely restore a mock back to its initial state?

mockClear() does, and also removes any mocked return values or implementations. This is useful when you want to completely reset a mock back to its initial state. (Note that resetting a spy will result in a function with no return value).

What is Jest mock ()?

Mock functions allow you to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls), capturing instances of constructor functions when instantiated with new , and allowing test-time configuration of return values.

How do you spyOn a function in Jest?

To spy on an exported function in jest, you need to import all named exports and provide that object to the jest. spyOn function. That would look like this: import * as moduleApi from '@module/api'; // Somewhere in your test case or test suite jest.


1 Answers

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
like image 165
Brian Adams Avatar answered Oct 20 '22 09:10

Brian Adams