How to automatically reset mocks and restore spies in Jest
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.
<!-- more -->When using Jest it seemed to be a common approach to manually invoke
jest.resetAllMocks() or jest.restoreAllMocks() inside a beforeEach(..)
or afterEach(..)
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 <br> <br> Is effectively the same as:<br>beforeEach(() => { jest.clearAllMocks(); }); -
“resetMocks”: true: same as “clearMocks”: true but also resets the behaviour of the mocks<br> <br> Is effectively the same as:<br>beforeEach(() => { jest.resetAllMocks(); }); -
“restoreMocks”: true: restores methods that were spied usingjest.spyOn(..)to its original method.<br> This flag is independent of the clearMocks / resetMocks flags.<br> <br> Is effective the same as:<br>beforeEach(() => { jest.restoreAllMocks(); });
The settings described above can be placed either:
- inside the
"jest""entry in thepackage.json - or in a Jest configuration file (typically called
jest.config.js)
I personally configured Jest by placing the following in package.json :
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(..) :
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');
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.