Skip to content

Commit 1fad0ca

Browse files
cjihrigeliphazbouye
authored andcommitted
test_runner: support module mocking
This commit adds experimental module mocking to the test runner. PR-URL: nodejs#52848 Fixes: nodejs#51164 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
1 parent 8156521 commit 1fad0ca

14 files changed

Lines changed: 1336 additions & 12 deletions

File tree

doc/api/cli.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,16 @@ generated as part of the test runner output. If no tests are run, a coverage
981981
report is not generated. See the documentation on
982982
[collecting code coverage from tests][] for more details.
983983

984+
### `--experimental-test-module-mocks`
985+
986+
<!-- YAML
987+
added: REPLACEME
988+
-->
989+
990+
> Stability: 1.0 - Early development
991+
992+
Enable module mocking in the test runner.
993+
984994
### `--experimental-vm-modules`
985995

986996
<!-- YAML

doc/api/test.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,25 @@ added:
17781778
Resets the implementation of the mock function to its original behavior. The
17791779
mock can still be used after calling this function.
17801780

1781+
## Class: `MockModuleContext`
1782+
1783+
<!-- YAML
1784+
added: REPLACEME
1785+
-->
1786+
1787+
> Stability: 1.0 - Early development
1788+
1789+
The `MockModuleContext` class is used to manipulate the behavior of module mocks
1790+
created via the [`MockTracker`][] APIs.
1791+
1792+
### `ctx.restore()`
1793+
1794+
<!-- YAML
1795+
added: REPLACEME
1796+
-->
1797+
1798+
Resets the implementation of the mock module.
1799+
17811800
## Class: `MockTracker`
17821801

17831802
<!-- YAML
@@ -1911,6 +1930,68 @@ test('spies on an object method', (t) => {
19111930
});
19121931
```
19131932

1933+
### `mock.module(specifier[, options])`
1934+
1935+
<!-- YAML
1936+
added: REPLACEME
1937+
-->
1938+
1939+
> Stability: 1.0 - Early development
1940+
1941+
* `specifier` {string} A string identifying the module to mock.
1942+
* `options` {Object} Optional configuration options for the mock module. The
1943+
following properties are supported:
1944+
* `cache` {boolean} If `false`, each call to `require()` or `import()`
1945+
generates a new mock module. If `true`, subsequent calls will return the same
1946+
module mock, and the mock module is inserted into the CommonJS cache.
1947+
**Default:** false.
1948+
* `defaultExport` {any} An optional value used as the mocked module's default
1949+
export. If this value is not provided, ESM mocks do not include a default
1950+
export. If the mock is a CommonJS or builtin module, this setting is used as
1951+
the value of `module.exports`. If this value is not provided, CJS and builtin
1952+
mocks use an empty object as the value of `module.exports`.
1953+
* `namedExports` {Object} An optional object whose keys and values are used to
1954+
create the named exports of the mock module. If the mock is a CommonJS or
1955+
builtin module, these values are copied onto `module.exports`. Therefore, if a
1956+
mock is created with both named exports and a non-object default export, the
1957+
mock will throw an exception when used as a CJS or builtin module.
1958+
* Returns: {MockModuleContext} An object that can be used to manipulate the mock.
1959+
1960+
This function is used to mock the exports of ECMAScript modules, CommonJS
1961+
modules, and Node.js builtin modules. Any references to the original module
1962+
prior to mocking are not impacted. The following example demonstrates how a mock
1963+
is created for a module.
1964+
1965+
```js
1966+
test('mocks a builtin module in both module systems', async (t) => {
1967+
// Create a mock of 'node:readline' with a named export named 'fn', which
1968+
// does not exist in the original 'node:readline' module.
1969+
const mock = t.mock.module('node:readline', {
1970+
namedExports: { fn() { return 42; } },
1971+
});
1972+
1973+
let esmImpl = await import('node:readline');
1974+
let cjsImpl = require('node:readline');
1975+
1976+
// cursorTo() is an export of the original 'node:readline' module.
1977+
assert.strictEqual(esmImpl.cursorTo, undefined);
1978+
assert.strictEqual(cjsImpl.cursorTo, undefined);
1979+
assert.strictEqual(esmImpl.fn(), 42);
1980+
assert.strictEqual(cjsImpl.fn(), 42);
1981+
1982+
mock.restore();
1983+
1984+
// The mock is restored, so the original builtin module is returned.
1985+
esmImpl = await import('node:readline');
1986+
cjsImpl = require('node:readline');
1987+
1988+
assert.strictEqual(typeof esmImpl.cursorTo, 'function');
1989+
assert.strictEqual(typeof cjsImpl.cursorTo, 'function');
1990+
assert.strictEqual(esmImpl.fn, undefined);
1991+
assert.strictEqual(cjsImpl.fn, undefined);
1992+
});
1993+
```
1994+
19141995
### `mock.reset()`
19151996

19161997
<!-- YAML

doc/node.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ Use this flag to enable ShadowRealm support.
185185
.It Fl -experimental-test-coverage
186186
Enable code coverage in the test runner.
187187
.
188+
.It Fl -experimental-test-module-mocks
189+
Enable module mocking in the test runner.
190+
.
188191
.It Fl -experimental-eventsource
189192
Enable experimental support for the EventSource Web API.
190193
.

0 commit comments

Comments
 (0)