Skip to content

jest.fn()

jest.fn() is the foundation of Jest's mocking system. This lesson covers how to create mock functions and configure exactly what they return or do when called.

Creating a Mock Function

jest.fn() with no arguments creates a mock that returns undefined by default when called, but still tracks every call. jest.fn(implementation) creates a mock that runs the given implementation function whenever it's called, which is useful when the fake needs to behave like a real (simplified) function.

Beyond creation, mock functions expose chainable configuration methods like .mockReturnValue() and .mockImplementation() that let you control behavior after the fact, even changing it between calls.

const add = jest.fn((a, b) => a + b);

expect(add(2, 3)).toBe(5);
expect(add).toHaveBeenCalledWith(2, 3);

Passing a real implementation to jest.fn() lets the mock behave like an actual function while still tracking calls.

Configuring Return Values

mockFn.mockReturnValue(42);
mockFn.mockReturnValueOnce(1).mockReturnValueOnce(2);
mockFn.mockImplementation((a, b) => a * b);
mockFn.mockResolvedValue({ ok: true });
mockFn.mockRejectedValue(new Error('failed'));
  • .mockReturnValue(x) makes every call return x.
  • .mockReturnValueOnce(x) queues a value for just the next call; chain multiple for a sequence.
  • .mockImplementation(fn) replaces the function's behavior entirely, including logic and side effects.
  • .mockResolvedValue()/.mockRejectedValue() are shortcuts for functions that return promises.

jest.fn() Cheat Sheet

Every common way to create and configure a mock function.

Method Effect
jest.fn() Creates a mock returning undefined
jest.fn(impl) Creates a mock running a custom implementation
.mockReturnValue(x) Always returns x
.mockReturnValueOnce(x) Returns x for just the next call
.mockImplementation(fn) Runs fn as the mock's logic
.mockImplementationOnce(fn) Runs fn for just the next call
.mockResolvedValue(x) Returns a promise resolved with x
.mockRejectedValue(err) Returns a promise rejected with err

Returning a Different Value on Each Call

.mockReturnValueOnce() (and .mockImplementationOnce()) can be chained multiple times to queue up a sequence of different results, one per call, falling back to any default set with .mockReturnValue() once the queue is exhausted.

const nextId = jest.fn()
  .mockReturnValueOnce(1)
  .mockReturnValueOnce(2)
  .mockReturnValue(3); // used for the 3rd call and beyond

expect(nextId()).toBe(1);
expect(nextId()).toBe(2);
expect(nextId()).toBe(3);
expect(nextId()).toBe(3);

Mocking Async Functions with mockResolvedValue

.mockResolvedValue(x) is shorthand for .mockImplementation(() => Promise.resolve(x)), and .mockRejectedValue(err) is shorthand for a rejected promise. Both make testing async dependencies dramatically simpler.

const fetchUser = jest.fn();

fetchUser.mockResolvedValue({ id: 1, name: 'Ada' });
await expect(fetchUser()).resolves.toEqual({ id: 1, name: 'Ada' });

fetchUser.mockRejectedValueOnce(new Error('Network error'));
await expect(fetchUser()).rejects.toThrow('Network error');

Common Mistakes

  • Using .mockImplementation() when the simpler .mockReturnValue() would do.
  • Forgetting .mockReturnValueOnce() values are consumed in order and run out if called too many times.
  • Writing .mockImplementation(() => Promise.resolve(x)) manually instead of .mockResolvedValue(x).
  • Not resetting mock implementations between tests, causing configuration from one test to leak into another.

Key Takeaways

  • jest.fn() creates a mock function, optionally with a custom implementation.
  • .mockReturnValue()/.mockImplementation() configure default behavior for every call.
  • .mockReturnValueOnce()/.mockImplementationOnce() queue behavior for specific calls only.
  • .mockResolvedValue()/.mockRejectedValue() simplify mocking promise-returning functions.

Pro Tip

Use .mockReturnValueOnce() chains to simulate a flaky dependency that fails once and then succeeds — it's a realistic and easy way to test retry logic.