JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicstestingMocking Functions, Modules, and APIs
PrevNext
testing
intermediate
15 min read

Mocking Functions, Modules, and APIs

isolation
jest.fn
jest.mock
mocking
msw
spyOn
vi.fn
vi.mock
vitest

How to use jest.fn(), jest.mock(), and jest.spyOn() (or their Vitest equivalents) to isolate code under test, plus API mocking with MSW for realistic network request testing.

Key Points

1Mock Functions (fn)

jest.fn() or vi.fn() creates standalone mock functions that record calls, arguments, and return values, configurable with mockReturnValue and mockImplementation.

2Module Mocking (mock)

jest.mock() or vi.mock() replaces entire modules with mocks. Use jest.requireActual for partial mocking to keep some exports real while mocking others.

3Spying on Methods (spyOn)

jest.spyOn() or vi.spyOn() watches existing methods without replacing them by default, recording calls while preserving original behavior with easy restoration.

4MSW for Network Mocking

Mock Service Worker intercepts HTTP requests at the network level, working with any HTTP client and providing the most realistic API mocking for integration tests.

5Mocking Boundaries

Mock external dependencies and services you do not control. Avoid over-mocking internal modules, which creates brittle tests coupled to implementation details.

What You'll Learn

  • Create and configure mock functions with jest.fn() or vi.fn() for various return scenarios
  • Mock entire modules and use partial mocking to keep some exports real
  • Use jest.spyOn() or vi.spyOn() to observe method calls without replacing behavior
  • Set up MSW for realistic API mocking in integration tests

Deep Dive

Mocking is the practice of replacing real dependencies with controlled substitutes during testing. It isolates the code under test so you can verify its behavior without relying on databases, APIs, or other modules. Jest and Vitest share nearly identical mocking APIs, making these patterns transferable between both runners.

jest.fn() / vi.fn() -- Mock Functions

Creates a standalone mock function that records all calls, arguments, and return values:

JavaScript
const mockCallback = jest.fn();
mockCallback('hello');
 
expect(mockCallback).toHaveBeenCalledTimes(1);
expect(mockCallback).toHaveBeenCalledWith('hello');

Mock functions can be configured to return specific values:

  • mockReturnValue(value): Always returns the specified value
  • mockReturnValueOnce(value): Returns the value once, then falls back to default
  • mockImplementation(fn): Replaces the function body entirely
  • mockResolvedValue(value): Returns a resolved promise (shorthand for async mocks)
  • mockRejectedValue(error): Returns a rejected promise

jest.mock() / vi.mock() -- Module Mocking

Replaces an entire module with a mock version. Jest hoists jest.mock() calls to the top of the file automatically:

JavaScript
jest.mock('./api'); // all exports become jest.fn()
import { fetchUsers } from './api';
 
fetchUsers.mockResolvedValue([{ name: 'Alice' }]);

For partial mocking (mock some exports, keep others real):

JavaScript
jest.mock('./utils', () => ({
  ...jest.requireActual('./utils'),
  formatDate: jest.fn(() => '2024-01-01'),
}));

jest.spyOn() / vi.spyOn() -- Spy on Methods

Watches an existing method without replacing it (by default), recording calls while preserving original behavior:

JavaScript
const spy = jest.spyOn(console, 'log');
someFunction();
expect(spy).toHaveBeenCalledWith('expected output');
spy.mockRestore(); // restore original implementation

Use .mockImplementation() on a spy to override the behavior while still being able to restore it later.

Mock Assertions

Key matchers for verifying mock behavior:

  • toHaveBeenCalled(): Function was called at least once
  • toHaveBeenCalledTimes(n): Called exactly n times
  • toHaveBeenCalledWith(args): Called with specific arguments
  • toHaveBeenLastCalledWith(args): Last call had these arguments
  • toHaveBeenNthCalledWith(n, args): Nth call had these arguments

API Mocking with MSW (Mock Service Worker)

MSW intercepts HTTP requests at the network level, providing the most realistic approach to API mocking:

JavaScript
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
 
const server = setupServer(
  http.get('/api/users', () => {
    return HttpResponse.json([{ id: 1, name: 'Alice' }]);
  })
);
 
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

MSW advantages over mocking fetch directly: works with any HTTP client (axios, fetch, ky), tests the full request/response cycle, and can be reused between tests and development.

When to Mock vs When Not To

  • Mock external services, APIs, and databases (things outside your control)
  • Mock time-dependent operations (Date.now, timers)
  • Do NOT mock the module you are testing
  • Avoid mocking everything -- over-mocking makes tests brittle and meaningless
  • Prefer integration tests with MSW over heavily mocked unit tests for components

Cleanup Best Practices

Always clear mocks between tests to prevent state leakage:

  • jest.clearAllMocks() / vi.clearAllMocks(): Resets call history and return values
  • jest.restoreAllMocks() / vi.restoreAllMocks(): Also restores original implementations
  • Configure restoreMocks: true in your config for automatic cleanup

Fun Fact

MSW (Mock Service Worker) was created by Artem Zakharchenko, a developer who was frustrated with mocking fetch in tests. MSW uses actual Service Worker API in the browser and request interception in Node.js, making it the only mocking tool that works identically in both environments.

Learn These First

Matchers and Assertions

beginner

Unit Testing Fundamentals

beginner

Continue Learning

Integration Tests vs Unit Tests

intermediate

React Testing Library

intermediate

Testing Asynchronous Code

beginner

Practice What You Learned

How do you mock functions, modules, and API calls in Jest?
mid
mocking
Jest provides jest.fn() for mock functions, jest.mock() for modules, and jest.spyOn() for spying on methods. For API calls, mock fetch/axios or use libraries like MSW. Mocks isolate code under test and allow controlling dependencies.
Previous
TDD vs BDD Methodologies
Next
Performance Testing and Budgets
PrevNext