Understanding Jest Mocks
Photo by Ferenc Almasi on Unsplash.
Jest is a powerful toolkit for testing JavaScript and TypeScript code. It's an all-in-one test runner, mocking framework, and assertion library. Without Jest, you might need to stitch together a separate library for each of these testing needs.
But I've always struggled to navigate Jest's complex mocking functionality. A long list of factors determine whether Jest replaces a module with fake logic (mocked) or executes the actual module (unmocked). To figure it out, I created a test project.
For the following questions, imagine you want to test a file which imports some-dependency
— which could be a local file, an npm package, or a built-in Node.js module.
1. Explicit unmock
Does the test call jest.unmock('some-dependency')
or jest.dontMock('some-dependency')
?
If no, continue to the next section.
If yes, some-dependency
will not be mocked.
2. Explicit mock
Does the test call jest.mock('some-dependency')
or jest.doMock('some-dependency')
?
If no, continue to the next section.
If the test uses the mock functions API like mockImplementation()
, mockReturnValue()
, or mockResolvedValue()
to specify the mock's behavior, some-dependency
will use that behavior.
Or if the jest.mock('some-dependency')
/ jest.doMock('some-dependency')
call includes the factory
parameter, some-dependency
will use the behavior specified by factory
.
Or if some-dependency
has a manual mock (a file in the appropriate /__mocks__/
directory), some-dependency
will use the behavior specified by that manual mock.
Otherwise Jest will autogenerate a default mock of some-dependency
using the substitution approach described in the docs for jest.createMockFromModule()
.
3. Core module
Is some-dependency
a core Node.js module?
If no, continue to the next section.
If yes, some-dependency
will not be mocked.
4. Automocking
Is Jest automocking enabled? Automocking may be enabled with automock: true
in the Jest configuration, or by calling jest.enableAutomock()
in the test.
If no, continue to the next section.
If some-dependency
has a manual mock (a file in the appropriate /__mocks__/
directory), some-dependency
will use the behavior specified by that manual mock.
Otherwise Jest will autogenerate a default mock of some-dependency
using the substitution approach described in the docs for jest.createMockFromModule()
.
5. Local module
Is some-dependency
a local file?
If no, continue to the next question.
If yes, some-dependency
will not be mocked.
6. Manual mock
Does some-dependency
have a manual mock (a file in the appropriate /__mocks__/
directory)?
If no, some-dependency
will not be mocked.
If yes, some-dependency
will use the behavior specified in the manual mock.