jestjs/jest · error · Error
received value must be a mock or spy function
Error message
received value must be a mock or spy function
What it means
Thrown by `ensureMockOrSpy` (spyMatchers.ts:1265), invoked from `toHaveBeenCalled`, `toHaveBeenCalledTimes`, `toHaveBeenCalledWith`, `toHaveBeenLastCalledWith`, and `toHaveBeenNthCalledWith`. It fires when the received value is neither a Jest mock function (`_isMockFunction === true`) nor a Jasmine-style spy (has `.calls.all` and `.calls.count` functions). These matchers read `received.mock.calls` or `received.calls`, which only exist on mocks/spies; a plain function or any other value would crash on property access.
Source
Thrown at packages/expect/src/spyMatchers.ts:1272
};
const isMock = (received: any) =>
received != null && received._isMockFunction === true;
const isSpy = (received: any) =>
received != null &&
received.calls != null &&
typeof received.calls.all === 'function' &&
typeof received.calls.count === 'function';
const ensureMockOrSpy = (
received: any,
matcherName: string,
expectedArgument: string,
options: MatcherHintOptions,
) => {
if (!isMock(received) && !isSpy(received)) {
throw new Error(
matcherErrorMessage(
matcherHint(matcherName, undefined, expectedArgument, options),
`${RECEIVED_COLOR('received')} value must be a mock or spy function`,
printWithType('Received', received, printReceived),
),
);
}
};
const ensureMock = (
received: any,
matcherName: string,
expectedArgument: string,
options: MatcherHintOptions,
) => {
if (!isMock(received)) {
throw new Error(
matcherErrorMessage(View on GitHub (pinned to f49721c78e)
Solutions
- Wrap the function with `jest.fn()`: `const fn = jest.fn();` then pass `fn` into the system under test.
- Use `jest.spyOn(obj, 'method')` to spy on an existing method before it is called.
- Verify the mock shape: log `received._isMockFunction` — should be `true`.
- If using a different fake library, adapt with a custom matcher or convert to `jest.fn()`.
Example fix
// before const send = (x) => x; system.run(send); expect(send).toHaveBeenCalled(); // not a mock // after const send = jest.fn(); system.run(send); expect(send).toHaveBeenCalled();
Defensive patterns
Strategy: type-guard
Validate before calling
if (received == null || received._isMockFunction !== true && !(received.calls?.all instanceof Function)) {
throw new Error('received must be a jest.fn() mock or jest.spyOn() spy');
}
expect(received).toHaveBeenCalled(); Type guard
const isMockOrSpy = (v: unknown): boolean =>
v != null &&
((v as any)._isMockFunction === true ||
(typeof (v as any).calls?.all === 'function' &&
typeof (v as any).calls?.count === 'function')); Try / catch
try {
expect(received).toHaveBeenCalled();
} catch (e) {
if (e instanceof Error && /must be a mock or spy function/.test(e.message)) {
console.error('received is not a mock/spy:', received);
}
throw e;
} Prevention
- Create mocks with `jest.fn()` and pass them into the system under test.
- Spy on existing methods with `jest.spyOn(obj, 'method')` before they are called.
- Verify `received._isMockFunction === true` before asserting in dynamic test setups.
When it happens
Trigger: Calling `expect(plainFn).toHaveBeenCalled()` where `plainFn` is a regular function (not wrapped with `jest.fn()`); `expect(callback).toHaveBeenCalledWith(...)` after passing a real implementation instead of a mock; `expect(obj.method).toHaveBeenCalled()` where `obj.method` was not spied on with `jest.spyOn(obj, 'method')`; passing a mock from a different test/library (vitest, sinon) that lacks the Jest mock shape.
Common situations: Forgetting to replace an injected dependency with `jest.fn()`; using `jest.spyOn` on a non-existent method; the spy was restored before the assertion; mixing Jest with another test framework's fakes; refactoring an injection such that the real implementation flows through.
Related errors
- received value must be a mock function
- ${expectedArgument} must be a positive integer
- expected value must be a number
- received value must be a number
- expected value must be a function
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/c281a64382b44615.json.
Report an issue: GitHub.