jestjs/jest · error · TypeError
Argument passed to callFake should be a function, got ${fn}
Error message
Argument passed to callFake should be a function, got ${fn} What it means
SpyStrategy.callFake(fn) replaces the spy's behavior with a user-supplied function. SpyStrategy.ts:90-95 throws a TypeError if fn is not a function, because the exec plan calls plan.apply(this, arguments) and a non-function would fail with a confusing error at call time. The guard fails fast with the offending value in the message.
Source
Thrown at packages/jest-jasmine2/src/jasmine/SpyStrategy.ts:92
const values = Array.prototype.slice.call(arguments);
plan = function () {
return values.shift();
};
return getSpy();
};
this.throwError = function (something) {
const error =
something instanceof Error ? something : new Error(something);
plan = function () {
throw error;
};
return getSpy();
};
this.callFake = function (fn) {
if (typeof fn !== 'function') {
throw new TypeError(
`Argument passed to callFake should be a function, got ${fn}`,
);
}
plan = fn;
return getSpy();
};
this.stub = function (_fn) {
plan = function () {};
return getSpy();
};
}
}
View on GitHub (pinned to f49721c78e)
Solutions
- Pass a function: spy.and.callFake(() => value) or spy.and.callFake(realFn).
- If you want a constant return, use spy.and.returnValue(value) instead of callFake.
- Inspect the interpolated fn in the message to find which non-function was passed and fix the binding.
Example fix
// before — value passed instead of function
spy.and.callFake({ status: 200 });
// after — wrap in a function (or use returnValue)
spy.and.callFake(() => ({ status: 200 }));
// or
spy.and.returnValue({ status: 200 }); Defensive patterns
Strategy: type-guard
Validate before calling
function callFakeSafe(spy: { and: { callFake: (fn: unknown) => unknown } }, fn: unknown) {
if (typeof fn !== 'function') {
throw new TypeError(`callFake expects a function, got ${typeof fn}`);
}
return spy.and.callFake(fn as Function);
} Type guard
function isFn(v: unknown): v is Function { return typeof v === 'function'; }
if (!isFn(fn)) throw new TypeError('callFake needs a function'); Prevention
- Use spy.and.returnValue(value) for constant returns instead of callFake(() => value) when no logic is needed.
- Type your spy helpers so a non-function callFake is a compile error.
- Double-check that you are passing the function itself, not its invocation result.
When it happens
Trigger: Calling `spy.and.callFake(someValue)` where someValue is not a function — e.g. a result object, undefined, a number, or a config. The `typeof fn !== 'function'` check at SpyStrategy.ts:91 throws TypeError at line 92.
Common situations: Passing the return value instead of the function (callFake(apiResponse) vs callFake(() => apiResponse)); a binding that resolved to undefined; refactor that changed the fake from a function to a value; passing an async function shape incorrectly.
Related errors
- Spies must be created in a before function or a spec
- Invalid second argument, ${specDefinitions}. It must be a ca
- Invalid second argument, ${fn}. It must be a callback functi
- Jasmine spies would overwrite the 'and' and 'calls' properti
- could not find an object to spy upon for ${methodName}()
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/94db76f62a1e6af4.json.
Report an issue: GitHub.