如何在Jest中正确Mock detect-node的isNode常量?
I've run into this exact issue before with Jest's module caching behavior interfering with mocks for third-party packages like detect-node. The core problem here is that your myTestFn is imported before your mocks are applied, so the original isNode value is cached and never updated. Here's a reliable solution that works with Jest ^26.4.2:
Solution: Reset Modules + Dynamic Import
We need to clear Jest's module cache before each test and dynamically import your function after applying the mock, ensuring the mock takes effect.
Updated Test File
describe('TEST', () => { // Reset module cache before every test to avoid cross-test contamination beforeEach(() => { jest.resetModules(); }); it('node mock false', async () => { // Mock detect-node FIRST, then dynamically import your function jest.doMock('detect-node', () => false); const { myTestFn } = await import('./fn'); myTestFn(); // Will log { isNode: false } }); it('node mock true', async () => { jest.doMock('detect-node', () => true); const { myTestFn } = await import('./fn'); myTestFn(); // Will log { isNode: true } }); });
Why This Works
jest.resetModules(): This clears Jest's internal module cache before each test run. Without this, the first imported version ofdetect-node(and yourfnmodule) would stay cached across tests, ignoring subsequent mocks.- Dynamic Import (
await import('./fn')): By importing your function inside the test case after callingjest.doMock, we ensure that whenfnloadsdetect-node, it uses our mocked value instead of the original.
Alternative: Mock with a Variable (For Reusable Mocks)
If you need to reuse the mock across tests, you can mock detect-node to return a mutable value that you can update between tests:
describe('TEST', () => { let mockIsNode; jest.mock('detect-node', () => { // Return a function that gives us control over the mock value return () => mockIsNode; }); beforeEach(() => { // Reset the mock value before each test mockIsNode = false; // Import the function here (after mock is set up) jest.isolateModules(() => { require('./fn'); }); }); it('node mock false', () => { mockIsNode = false; const { myTestFn } = require('./fn'); myTestFn(); }); it('node mock true', () => { mockIsNode = true; const { myTestFn } = require('./fn'); myTestFn(); }); });
This approach uses jest.mock to create a controllable mock, and jest.isolateModules to ensure the module loads with the current mock value.
Either of these methods should resolve your issue and let you toggle the isNode value between tests as expected.
内容的提问来源于stack exchange,提问作者nirebam368

