-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Module level mocking #51164
Comments
When I was searching for a workaround, how to mock imports with the native test runner I found this looking very similar: https://github.com/nodejs/node/blob/main/test/es-module/test-esm-loader-mock.mjs I can't tell if this is already integrated, just missing the new types in @types/node? |
It's already possible to mock things as the test linked below using the experimental Customization Hook API (https://nodejs.org/api/module.html#customization-hooks). Note that it should work only on Node.js 18.19+/20.6+. Here are the files to set it up, and as you can see, it's only using public APIs: https://github.com/nodejs/node/blob/6a5394ea7dc62b044ed826a7c8d18506ab532b96/test/fixtures/es-module-loaders/mock.mjs |
This information should be added to the test runner docs. I was searching for a working solution to mock modules for days. |
@aduh95 thanks, but these files leave me confused. The path of these things If so, then are we supposed to replicate such a weighty setup in every project where we want to mock module methods? Or do you know if a nicer/lighter way will end up shipping to test_runner? Is there a reason it's not exposed yet, or is the reason merely "because nobody shipped it yet"? |
Not at all, it's a test that validates mocking of module works (and keeps working). Node.js own tests do not need mocking.
Well nobody shipped it yet indeed, I haven't tried myself so I can't tell you what would be the road blockers. I think it should be feasible to create an npm package that exposes a mock API. |
Thx @aduh95, understood. Note to future self and passerbys: there’s similar discussion and links on stubbing ESM modules at sinonjs/sinon#1832, some of it is probably useful outside of Sinon and in the context of mocking with Node-builtin |
From https://cjihrig.com/test_runner_wishlist_2024 (2024-01-09):
Hooks are RC in 21. Not sure how current Colin's opinion is since wip branch is from August 2023. Thank you Colin and everyone else who led me here. Open source can be hard. |
Just a heads up - I plan to resume working on this. It will need to be an experimental feature though until the underlying modules APIs stabilize. |
I made a simple script to replace a module to fixtures files
// mock-module.js
import { stat } from "node:fs/promises";
import { join, relative } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
const packageDistDir = fileURLToPath(new URL("./dist", import.meta.url));
const fixturesDir = fileURLToPath(new URL("./fixtures", import.meta.url));
export async function resolve(specifier, context, nextResolve) {
const result = await nextResolve(specifier, context);
if (result.format === "builtin" || result.url.startsWith("node:")) {
return result;
}
const targetUrl = fileURLToPath(result.url).replace(/\.js$/, ".ts");
const relativePath = relative(packageDistDir, targetUrl);
if (relativePath.startsWith(".") || relativePath.startsWith("/")) {
return result;
}
const url = pathToFileURL(join(fixturesDir, relativePath)).toString();
const exist = await stat(fileURLToPath(url))
.then((stat) => stat.isFile())
.catch((err) => {
if (err.code === "ENOENT") {
return false;
}
throw err;
});
if (!exist) {
return result;
}
return {
url,
format: "module",
};
} // mock-register.js
import { register } from "node:module";
register("./mock-module.js", import.meta.url); node --import tsx --import ./mock-register.js --test ./tests/index.test.ts |
This commit adds experimental module mocking to the test runner. PR-URL: #52848 Fixes: #51164 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
This commit adds experimental module mocking to the test runner. PR-URL: #52848 Fixes: #51164 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
This commit adds experimental module mocking to the test runner. PR-URL: nodejs#52848 Fixes: nodejs#51164 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
This commit adds experimental module mocking to the test runner. PR-URL: nodejs#52848 Fixes: nodejs#51164 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
This commit adds experimental module mocking to the test runner. PR-URL: #52848 Fixes: #51164 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
What is the problem this feature will solve?
Currently you can't mock external or built-in modules which makes it difficult if you code imports a module that may run some side-effects and you have no control over it.
There may be some built in modules which you need to stub out but don't have access to during a test run.
What is the feature you are proposing to solve the problem?
Allowing us to use the built-in test runner to mock modules entirely.
There has already been some work in this by @cjihrig
I think the biggest things missing before I can open a PR are related to ESM loaders and are tracked in #49472 and #49473.
Both of those issues look to be resolved now, I don't know what the current blockers are for this
What alternatives have you considered?
No response
The text was updated successfully, but these errors were encountered: