Skip to content
Sarj Code Standards

no-first-party-module-mock

Prefer injected collaborators over mocking maintained first-party modules in tests.

Why

Replacing an owned module couples tests to its lookup path and can verify mock wiring while bypassing the real implementation contract.

Fix

Extract a narrow port or pure core operation and inject a typed fake; retain module mocking only when module lookup or bootstrap behavior is the contract.

Examples

Before — flagged Do not replace an owned module
action.test.ts
import { vi } from "vitest";
vi.mock("./service", () => ({ run: vi.fn() }));
After — preferred Inject a narrow service port
action.test.ts
const result = await runAction({ service: recordingService });
Before — flagged Exercise the maintained ESM implementation — before
tests/service.test.ts
import { jest } from "@jest/globals";
jest.unstable_mockModule("./service.js", () => ({}));
After — preferred Exercise the maintained ESM implementation — after
tests/service.test.ts
import { run } from "./service.js";
run();

Options

{
"additionalProperties": false,
"properties": {
"additionalModulePrefixes": {
"description": "Additional maintained module prefixes that tests must not mock.",
"items": { "minLength": 1, "type": "string" },
"type": "array",
"uniqueItems": true
}
},
"type": "object"
}

References