jestjs/jest · error · Error

${RECEIVED_COLOR('received')} value must be a mock function

Error message

${RECEIVED_COLOR('received')} value must be a mock function

What it means

Thrown by `ensureMock` (spyMatchers.ts:1288), used by toHaveReturned, toHaveReturnedTimes, toHaveReturnedWith, toHaveLastReturnedWith, and toHaveNthReturnedWith. It fires when the received value is a Jest mock (`_isMockFunction === true`) is false. These return-value matchers need `received.mock.results`, which only Jest mocks expose — a Jasmine spy (which has `.calls` but no `.mock.results`) is also rejected, hence a stricter guard than ensureMockOrSpy.

Source

Thrown at packages/expect/src/spyMatchers.ts:1289

  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(
        matcherHint(matcherName, undefined, expectedArgument, options),
        `${RECEIVED_COLOR('received')} value must be a mock function`,
        printWithType('Received', received, printReceived),
      ),
    );
  }
};

export default spyMatchers;

View on GitHub (pinned to 8e6d128e4a)

Solutions

  1. Use jest.fn() so the function has a .mock.results array: const fn = jest.fn().
  2. If you only have a spy and need call-count semantics, use toHaveBeenCalledWith (which accepts spies) instead of the toHaveReturned family.
  3. Confirm the reference passed to expect() is the jest.fn() itself, not a wrapper or the original.
  4. Ensure module isolation so the mock attaches where the code actually calls it.

Example fix

// before
const fn = jasmine.createSpy('fn'); // or a plain fn
fn();
expect(fn).toHaveReturnedWith(undefined); // not a jest mock

// after
const fn = jest.fn();
fn();
expect(fn).toHaveReturnedWith(undefined);
// if you must use a spy, use call-based matchers
expect(fn).toHaveBeenCalled();
Defensive patterns

Strategy: type-guard

Validate before calling

const fn = received;
if (!(fn != null && fn._isMockFunction === true)) {
  throw new Error('return matchers require a jest.fn() (not a plain fn or jasmine spy)');
}
expect(fn).toHaveReturnedWith(value);

Type guard

const isJestMock = (v: unknown): boolean =>
  v != null && (v as any)._isMockFunction === true;

Prevention

When it happens

Trigger: Calling `expect(fn).toHaveReturnedWith(value)` where fn is a plain function, a Jasmine spy (has .calls but not .mock), undefined, or any non-Jest-mock value.

Common situations: Using a Jasmine-style spy (e.g. from an older/jasmine-jquery setup) and expecting Jest return semantics; forgot jest.fn(); passing the original function instead of the mock; the mock was lost after a re-import.

Related errors


AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10). Data as JSON: /api/errors/973c527dc63d3130. Report an issue: GitHub.