Mock modules
Rstest supports mocking modules, which allows you to replace the implementation of modules in tests. Rstest provides utility functions in rs (rstest) for mocking modules. You can directly use the following methods to mock modules:
rs.mock
- Type:
<T = unknown>(moduleName: string | Promise<T>, moduleFactory?: (() => Partial<T>)) => void
When calling rs.mock, Rstest will mock and replace the module specified in the first parameter. rs.mock will determine how to handle the mocked module based on whether a second mock factory function is provided, as explained in detail below.
Note that: rs.mock is hoisted to the top of the current module, so even if you execute import fn from 'some_module' before calling rs.mock('some_module'), some_module will be mocked from the beginning.
Based on the second parameter provided, rs.mock has two behaviors:
- If a factory function is provided as the second parameter to
rs.mock, the module will be replaced with the return value of the factory function as the implementation of the mocked module.
-
If
rs.mockis called without providing a factory function, it will attempt to resolve a module with the same name in the__mocks__directory at the same level as the mocked module. The specific mock resolution rules are as follows:- If the mocked module is not an npm dependency, and there is a
__mocks__folder at the same level as the file being mocked, where the__mocks__folder contains a file with the same name as the mocked module, Rstest will use that file as the mock implementation. - If the mocked module is an npm dependency, and there is a
__mocks__folder in the root directory that contains a file with the same name as the mocked module, Rstest will use that file as the mock implementation. - If the mocked module is a Node.js built-in module (such as
fs,path, etc.), and there is a__mocks__folder in the root directory that contains a file with the same name as the built-in module (e.g.,__mocks__/fs.mjs,__mocks__/path.ts, etc.), Rstest will use that file as the corresponding mock implementation (when using thenode:protocol to import built-in modules, thenode:prefix will be ignored).
For example, if the project has the following file structure:
Then in the following test file, when trying to mock the
lodashandsrc/multiplemodules, they will be replaced with implementations from__mocks__/lodash.jsandsrc/__mocks__/multiple.ts.src/multiple.test.tsrs.mockandrs.doMockalso support passing aPromise<T>as the first parameter, and use the typeTas the return value type of the second factory function after awaiting (Promise<T>). This provides better type hints in IDEs and type validation for the factory function's return value. PassingPromise<T>only enhances type hints and has no impact on the module mocking capabilities. - If the mocked module is not an npm dependency, and there is a
rs.doMock
- Type:
<T = unknown>(moduleName: string | Promise<T>, moduleFactory?: (() => Partial<T>)) => void
Similar to rs.mock, rs.doMock also mocks modules, but it is not hoisted to the top of the module. It is called when it's executed, which means that if a module has already been imported before calling rs.doMock, that module will not be mocked, while modules imported after calling rs.doMock will be mocked.
rs.importActual
- Type:
<T = Record<string, unknown>>(path: string) => Promise<T>
Loads the original implementation of a module even if it has already been mocked. Use rs.importActual when you want a partial mock so you can merge the real exports with your overrides.
Rstest also exposes a synchronous importActual option for static imports. Add the import attribute with { rstest: 'importActual' } to load the real module as the file evaluates:
rs.importMock
- Type:
<T = Record<string, unknown>>(path: string) => Promise<T>
Imports a module and all its properties as mock implementations.
rs.unmock
- Type:
(path: string) => void
Cancels the mock implementation of the specified module. After this, all calls to import will return the original module, even if it was previously mocked. Like rs.mock, this call is hoisted to the top of the file, so it will only cancel module mocks executed in setupFiles.
rs.doUnmock
- Type:
(path: string) => void
Same as rs.unmock, but it is not hoisted to the top of the file. The next import of the module will import the original module instead of the mock. This will not cancel modules that were imported before the mock.
rs.resetModules
- Type:
resetModules: () => RstestUtilities
Clears the cache of all modules. This allows modules to be re-executed when re-imported. This is useful for isolating the state of modules shared between different tests.
Does not reset mocked modules. To clear mocked modules, use rs.unmock or rs.doUnmock.