Skip to content

mock.module.restore fails if module is already present in ESM cache #61841

@NiedziolkaMichal

Description

@NiedziolkaMichal

A typical reason to mock modules, is to replace return value of a function imported from a tested module.
Lets consider two very simple modules:

// main.ts
import { getValue } from "./util.ts";

export function main() {
    return 'received ' + getValue();
}
// util.ts
export function getValue() {
    return "real value";
}

What I would like to do, is mock the getValue always, once or when there are a given input arguments.

Now take a look at the test:

import { it } from 'node:test';
import assert from "node:assert";

it('should return mock value', async (t) => {
    const mock = t.mock.module('./util.ts', {
        namedExports: {
            getValue() {
                return "mock";
            },
        },
    });

    const { main } = await import('./main.ts');

    assert.equal(main(), 'received mock');

    mock.restore();
})

it('should return original value', async () => {
    let { main } = await import('./main.ts');

    assert.equal(main(), 'received real value');
})

The second test fails, because mock wasn't restored.
Now if we switch the tests and put should return original value first, the test should return mock value fails, because mock.module doesn't invalidate modules which already imported the mocked module. Those two issues makes it practically impossible to mock modules, especially with --test-isolation=none.

Using node test runner with default test-isolation is unusable for any large project, due to terrible performance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    test_runnerIssues and PRs related to the test runner subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions