Jest · Unit tests that survive refactors

How does jest.mock work and why does hoisting matter?

Hardmodule mockingjest.mockhoistingUpdated Oct 2026
Quiz this track

Short answer

jest.mock replaces a module's exports for the test file and is hoisted above imports. Its factory cannot close over ordinary outer variables unless they are named with a mock prefix.

When a module is imported, Jest resolves it through its own registry. jest.mock registers a replacement for that path before the module is required. Babel and ts-jest hoist the call to the top of the file so the replacement exists by the time the import runs.

ts
jest.mock("./mailer", () => ({
  sendEmail: jest.fn().mockResolvedValue({ ok: true }),
}));

import { sendEmail } from "./mailer";
import { notifyUser } from "./notify";

test("sends one email", async () => {
  await notifyUser("asha@example.com");
  expect(sendEmail).toHaveBeenCalledTimes(1);
});
The factory replaces the real mailer before the import is evaluated.

The hoisting rule

  • The jest.mock call is moved above imports by the transform
  • A factory referencing a top-level variable can fail with a module initialization error
  • Variables prefixed with mock are allowed by the hoist guard
  • Use jest.requireActual inside the factory to keep real exports
  • Use jest.requireMock to read the replacement
ts
jest.mock("./mailer", () => {
  const actual = jest.requireActual("./mailer");

  return {
    ...actual,
    sendEmail: jest.fn(),
  };
});
Partial mocking keeps the real exports and replaces only the expensive or external one.

jest.mock is file-scoped. It applies to the module registry used by that test file, not to other files. If you need a different mock per test, import the mocked module and change the implementation with mockImplementation, or call jest.resetModules() and re-require carefully.

A module mock is a strong claim that the real module is not part of the behaviour under test. If the real module is cheap and deterministic, prefer a spy or a plain dependency injection over a full replacement.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Why does a jest.mock factory fail when it references an outer variable?
  2. 2How do you partially mock a module?
  3. 3Does jest.mock affect other test files?
  4. 4When is jest.resetModules necessary?

Say it in the interview

jest.mock replaces a module's exports for the current test file. The transform hoists it above imports so the replacement is registered before the import runs. That hoisting is why a factory cannot freely reference outer variables; the prefix mock is the escape hatch. For partial mocks I use jest.requireActual and spread the real exports, then override one function.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Jest mock interview and get scored feedback on depth, clarity and confidence.