Skip to content

Jest Manual Mocks

Instead of repeating a jest.mock() factory in every test file, Jest lets you define a reusable mock once in a __mocks__ folder. This lesson covers manual mocks for both local modules and npm packages.

The __mocks__ Folder Convention

For a local module at src/emailClient.js, you can create src/__mocks__/emailClient.js with the mock implementation. Once this file exists, calling jest.mock('./emailClient') (with no factory) automatically uses it instead of auto-mocking, without repeating the fake logic in every test file.

This is especially valuable when several test files need the same mocked module — the mock logic lives in one place instead of being duplicated across the codebase.

// src/__mocks__/emailClient.js
module.exports = {
  send: jest.fn().mockResolvedValue({ delivered: true }),
};

// any test file
jest.mock('../emailClient'); // uses the manual mock automatically
const emailClient = require('../emailClient');

No factory function is needed in the test file — Jest finds the manual mock automatically based on the folder convention.

Manual Mocks for npm Packages

// __mocks__/axios.js (at the project root, next to node_modules)
module.exports = {
  get: jest.fn().mockResolvedValue({ data: {} }),
  post: jest.fn().mockResolvedValue({ data: {} }),
};
  • For node_modules packages, place the mock in a __mocks__ folder at the project root (adjacent to node_modules).
  • Manual mocks for node_modules packages are used automatically — no jest.mock() call is even required in the test file.
  • Manual mocks for local (relative-path) modules still require a jest.mock('./path') call to activate.
  • Keep manual mocks simple; they should behave predictably, not replicate every real edge case.

Manual Mocks Cheat Sheet

Where to put manual mocks depending on what you're mocking.

What You're Mocking Mock File Location Needs jest.mock()?
Local module (src/emailClient.js) src/__mocks__/emailClient.js Yes
npm package (axios) __mocks__/axios.js (project root) No, applied automatically
Node.js core module (fs) __mocks__/fs.js (project root) Yes (jest.mock('fs'))

Manually Mocking Node.js Core Modules

Node.js built-in modules like fs or path require an explicit jest.mock('fs') call even if a manual mock file exists, because Jest treats core modules slightly differently from regular npm packages for safety reasons.

// __mocks__/fs.js
module.exports = {
  readFileSync: jest.fn().mockReturnValue('{"mocked":true}'),
};

// test file
jest.mock('fs');
const fs = require('fs');

test('reads config using the mocked fs module', () => {
  expect(fs.readFileSync('config.json')).toBe('{"mocked":true}');
});

Keeping Manual Mocks Simple and Realistic

A manual mock should mirror the real module's shape (same function names, similar return structure) without trying to replicate every internal detail. Overly clever manual mocks can drift from real behavior over time and hide genuine regressions.

  • Match the real module's exported function names exactly.
  • Return realistic, minimal example data instead of deeply nested fake objects.
  • Revisit manual mocks whenever the real module's API changes.

Common Mistakes

  • Placing a local module's manual mock in the wrong relative __mocks__ folder location.
  • Forgetting that node_modules manual mocks apply automatically without a jest.mock() call.
  • Letting a manual mock drift out of sync with the real module's actual API over time.
  • Writing an overly complex manual mock instead of a simple factory-based jest.mock() call.

Key Takeaways

  • Manual mocks live in a __mocks__ folder next to the module (or at the root for npm/core packages).
  • Local module manual mocks still need an explicit jest.mock() call to activate.
  • npm package and Node.js core module manual mocks are more automatic but have their own quirks.
  • Manual mocks are best for shared, reusable fakes used across many test files.

Pro Tip

Reserve manual mocks (__mocks__ folders) for modules mocked identically across many test files. For one-off mocking needs, an inline jest.mock('./x', () => ({...})) factory is usually simpler to read.