Manual mocks are used to stub out functionality with mock data. For example, instead of accessing a remote resource like a website or a database, you might want to create a manual mock that allows you to use fake data. This ensures your tests will be fast and not flaky.
Manual mocks are defined by writing a module in a
__mocks__/ subdirectory immediately adjacent to the module. For example, to mock a module called
user in the
models directory, create a file called
user.js and put it in the
models/__mocks__ directory. Note that the
__mocks__ folder is case-sensitive, so naming the directory
__MOCKS__ will break on some systems.
When we require that module in our tests, explicitly calling
If the module you are mocking is a Node module (e.g.:
lodash), the mock should be placed in the
__mocks__ directory adjacent to
node_modules (unless you configured
roots to point to a folder other than the project root) and will be automatically mocked. There's no need to explicitly call
Scoped modules (also known as scoped packages) can be mocked by creating a file in a directory structure that matches the name of the scoped module. For example, to mock a scoped module called
@scope/project-name, create a file at
__mocks__/@scope/project-name.js, creating the
@scope/ directory accordingly.
Warning: If we want to mock Node's core modules (e.g.:
path), then explicitly calling e.g.
jest.mock('path')is required, because core Node modules are not mocked by default.
When a manual mock exists for a given module, Jest's module system will use that module when explicitly calling
jest.mock('moduleName'). However, when
automock is set to
true, the manual mock implementation will be used instead of the automatically created mock, even if
jest.mock('moduleName') is not called. To opt out of this behavior you will need to explicitly call
jest.unmock('moduleName') in tests that should use the actual module implementation.
Note: In order to mock properly, Jest needs
jest.mock('moduleName')to be in the same scope as the
Here's a contrived example where we have a module that provides a summary of all the files in a given directory. In this case, we use the core (built in)
Since we'd like our tests to avoid actually hitting the disk (that's pretty slow and fragile), we create a manual mock for the
fs module by extending an automatic mock. Our manual mock will implement custom versions of the
fs APIs that we can build on for our tests:
Now we write our test. Note that we need to explicitly tell that we want to mock the
fs module because it’s a core Node module:
The example mock shown here uses
jest.createMockFromModule to generate an automatic mock, and overrides its default behavior. This is the recommended approach, but is completely optional. If you do not want to use the automatic mock at all, you can export your own functions from the mock file. One downside to fully manual mocks is that they're manual – meaning you have to manually update them any time the module they are mocking changes. Because of this, it's best to use or extend the automatic mock when it works for your needs.
To ensure that a manual mock and its real implementation stay in sync, it might be useful to require the real module using
jest.requireActual(moduleName) in your manual mock and amending it with mock functions before exporting it.
The code for this example is available at examples/manual-mocks.
If you're using ES module imports then you'll normally be inclined to put your
import statements at the top of the test file. But often you need to instruct Jest to use a mock before modules use it. For this reason, Jest will automatically hoist
jest.mock calls to the top of the module (before any imports). To learn more about this and see it in action, see this repo.
If some code uses a method which JSDOM (the DOM implementation used by Jest) hasn't implemented yet, testing it is not easily possible. This is e.g. the case with
window.matchMedia(). Jest returns
TypeError: window.matchMedia is not a function and doesn't properly execute the test.
In this case, mocking
matchMedia in the test file should solve the issue:
This works if
window.matchMedia() is used in a function (or method) which is invoked in the test. If
window.matchMedia() is executed directly in the tested file, Jest reports the same error. In this case, the solution is to move the manual mock into a separate file and include this one in the test before the tested file: