How to automatically reset mocks and restore spies in Jest

by Emil — 3 minutes

When I used jest for the first time for unit testing, it struck me that function mocks and spies were not automatically reset / restored before each unit test execution. This was quite unexpected to me, especially when you are used to automatic reset / restore functionality of Jasmine.

When using Jest it seemed to be a common approach to manually invoke jest.resetAllMocks() or jest.restoreAllMocks() inside a beforeEach(..) or afterEach(..)

const myMock = jest.fn();

describe('..', () => {
  beforeEach(() => {
    jest.resetAllMocks();
  });

Configuring Jest to automatically reset / restore mocks and spies

As it seemed, it turned out Jest can be configured to do an automatic reset / restore before executing each unit test spec.

You can simply use these settings in the configuration of Jest:

  • “clearMocks”: true: resets all the mocks usage data, but keeps the behaviour (e.g. return value) of the mocks

    Is effectively the same as:
    beforeEach(() => { jest.clearAllMocks(); });
  • “resetMocks”: true : same as “clearMocks”: true but also resets the behaviour of the mocks

    Is effectively the same as:
    beforeEach(() => { jest.resetAllMocks(); });
  • “restoreMocks”: true : restores methods that were spied using jest.spyOn(..) to its original method.
    This flag is independent of the clearMocks / resetMocks flags.

    Is effective the same as:
    beforeEach(() => { jest.restoreAllMocks(); });

The settings described above can be placed either:

  • inside the "jest"" entry in the package.json
  • or in a Jest configuration file (typically called jest.config.js)

I personally configured Jest by placing the following in package.json :

{
  ..
  "jest": {
    ..
    "resetMocks": true,
    "restoreMocks": true
  }
}

NOTE: when using Create React App the only officially supported way to configure Jest is through the package.json file.

How to properly spy on existing methods

Once in a while you need to replace a method of an existing (global) object with a Jest spy. For instance to be able to test if and how a method was called, or even to temporarily replace the behaviour of the method (e.g. returning a mocked return value).

The poor man's way to spy on a method would to simply monkey-patch an object, by simply assigning the result of jest.fn(..) :

window.open = jest.fn(); // X do “not” do this !!!

However, when manually replacing an existing method with a jest.fn(..), you’re also responsible to restore the original method.

Instead, it’s much better to use jest.spyOn(..), in which case Jest automatically resets the spy when “restoreMocks”: true is configured.

Since “restoreMocks”: true automatically restores a spy prior to executing each unit test spec (and prior to any custom beforeEach(..) ), it's best to only use jest.spyOn(..) inside either:

  • a beforeEach(..)
  • a unit test spec

Whereas the following usage of jest.spyOn(..) will give issues:

jest.spyOn(window, 'open');

describe('...', () => {
  it('...', () => { // you will get a fresh spy here
    // ..
    expect(window.open).toHaveBeenCalled();
  }

  it('...', () => { // X window.open is no longer a spy
    // ..
    expect(window.open).toHaveBeenCalled();

How to prevent method overrides with jest.fn()

To guard your codebase against the overriding a method by reassigning it with jest.fn(..) , you could configure the ESLint linter to use the prefer-spy-on rule.

meerdivotion

Cases

Blogs

Event