100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

Mocking Modules with jest.mock()

Understand how jest.mock() replaces entire modules with automatic or manual mocks, and how to combine that with jest.requireActual for partial mocking.

MockingIntermediate9 min readJul 10, 2026
Analogies

Why Mock Entire Modules?

A unit test should exercise the logic in the file under test, not the behavior of everything it imports. When a module reaches out to the filesystem, hits a real database, or calls a third-party API, jest.mock('./path/to/module') replaces every import of that module in the current test file with a fake version, cutting the dependency entirely. This is a different tool than jest.fn() alone: instead of stubbing one function you control directly, jest.mock() intercepts the module resolution system itself so any file importing that module gets the fake automatically.

🏏

Cricket analogy: Replacing a live stadium pitch with a practice net during training, so a batsman like Rohit Sharma can drill technique without match-day variables, mirrors jest.mock() swapping a real module for a controlled fake.

Automatic vs Manual Mocks

Calling jest.mock('./userService') with no second argument triggers automatic mocking: Jest inspects the module's shape and replaces every exported function with a jest.fn() that returns undefined by default, while non-function exports are kept as-is. For more control, you create a manual mock — a file with the same name placed inside a __mocks__ folder next to the real module (or at the project root for node_modules packages) — that Jest will use automatically once jest.mock() is called, giving you a hand-written fake implementation reused across every test file that mocks it.

🏏

Cricket analogy: Using a bowling machine's default settings (automatic mock) versus programming a custom line-and-length routine (manual mock in __mocks__) mirrors jest.mock()'s automatic mocking versus a manual mock file.

javascript
// __mocks__/axios.js
export default {
  get: jest.fn(() => Promise.resolve({ data: { id: 1 } })),
};

// user.test.js
jest.mock('axios');
import axios from 'axios';
import { fetchUser } from './user';

test('fetches user data', async () => {
  axios.get.mockResolvedValueOnce({ data: { id: 1, name: 'Ada' } });
  const user = await fetchUser(1);
  expect(user.name).toBe('Ada');
  expect(axios.get).toHaveBeenCalledWith('/users/1');
});

Mocking Node Modules and Factory Functions

For third-party npm packages, jest.mock('module-name', factory) lets you supply a factory function inline that returns the fake module shape, which is especially handy for a package like axios where you only need get, post, and defaults stubbed rather than the entire API surface. This inline factory approach avoids creating a __mocks__ file when the fake behavior is specific to a single test file, and it runs before any import statement executes because Babel hoists jest.mock() calls to the top of the module.

🏏

Cricket analogy: Telling a scoring app to always report DRS as 'not out' via a scripted factory response resembles jest.mock('module', factory) supplying a custom fake implementation for an entire package.

Jest hoists jest.mock() calls to the top of the file (above imports) via babel-plugin-jest-hoist, so you can safely write jest.mock('./api') before the import statement — but this also means you cannot reference out-of-scope variables inside the factory unless the variable name is prefixed with 'mock'.

Partial Mocking with jest.requireActual

Sometimes you want most of a module's real behavior but need to override just one export — for example, keeping a real formatCurrency helper while faking a network-dependent fetchExchangeRate. jest.requireActual('./module') retrieves the genuine, unmocked module regardless of any active jest.mock() call, so inside a factory you can spread the real module's exports and override only the specific property you need faked, preserving real logic everywhere else.

🏏

Cricket analogy: Keeping a fielder's real throwing arm but scripting only the run-out decision, like requireActual keeping most exports real while overriding one, is jest.requireActual mixed with selective mocking.

jest.mock() calls are hoisted above imports by Babel, so referencing a local variable inside the factory function throws an 'out-of-scope variable' reference error unless the variable name starts with 'mock' (e.g., mockAxios).

  • jest.mock('./path') swaps an entire module with an automatic or manual mock for every import in that test file.
  • Automatic mocks replace every exported function with a jest.fn() that returns undefined by default.
  • Manual mocks live in a __mocks__ folder adjacent to the real module (or at the root for node_modules) and give full control over fake behavior.
  • jest.mock('module', factory) lets you supply a custom factory function returning the fake implementation inline in the test file.
  • jest.requireActual('./module') retrieves the real, unmocked module so you can keep most exports genuine while overriding just one.
  • jest.mock() calls are hoisted above import statements by Babel, which affects what variables the factory function can reference.
  • Mocking entire modules is the right tool when a dependency touches the filesystem, network, or database — not for controlling a single function's return value.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#JestStudyNotes#TestingQA#MockingModulesWithJestMock#Mocking#Modules#Jest#Mock#StudyNotes#SkillVeris