vitest-dev/vitest · error · AssertionError
${formatCalls(spy, msg, args)}
Error message
${formatCalls(spy, msg, args)} What it means
AssertionError thrown by toHaveBeenCalledWith/toBeCalledWith when the spy was never called with the exact arguments (positive form) or was called with them under .not. The message is enriched by formatCalls, which lists every received call with a diff against the expected arguments.
Source
Thrown at packages/expect/src/jest-expect.ts:614
jestEquals(aItem, b[i], [...customTesters, iterableEquality]),
)
}
def(['toHaveBeenCalledWith', 'toBeCalledWith'], function (...args) {
const spy = getSpy(this)
const spyName = spy.getMockName()
const pass = spy.mock.calls.some(callArg => equalsArgumentArray(callArg, args))
const isNot = utils.flag(this, 'negate') as boolean
const msg = utils.getMessage(this, [
pass,
`expected "${spyName}" to be called with arguments: #{exp}`,
`expected "${spyName}" to not be called with arguments: #{exp}`,
args,
])
if ((pass && isNot) || (!pass && !isNot)) {
throw new AssertionError(formatCalls(spy, msg, args))
}
})
def('toHaveBeenCalledExactlyOnceWith', function (...args) {
const spy = getSpy(this)
const spyName = spy.getMockName()
const callCount = spy.mock.calls.length
const hasCallWithArgs = spy.mock.calls.some(callArg => equalsArgumentArray(callArg, args))
const pass = hasCallWithArgs && callCount === 1
const isNot = utils.flag(this, 'negate') as boolean
const msg = utils.getMessage(this, [
pass,
`expected "${spyName}" to be called once with arguments: #{exp}`,
`expected "${spyName}" to not be called once with arguments: #{exp}`,
args,
])
if ((pass && isNot) || (!pass && !isNot)) {View on GitHub (pinned to d568f8ce37)
Solutions
- Read the per-call diff in the failure output to find which argument differs.
- If only a subset of arguments matters, wrap expected args with asymmetric matchers (expect.objectContaining, expect.any).
- Confirm the spy captured the call you think it did — check spy.mock.calls in a debug step.
Example fix
// before
expect(log).toHaveBeenCalledWith('user', 42);
// after (relax shape)
expect(log).toHaveBeenCalledWith('user', expect.any(Number)); Defensive patterns
Strategy: validation
Validate before calling
const recorded = spy.mock.calls;
if (!recorded.some(c => c.length === args.length && c.every((v, i) => jestEquals(v, args[i])))) {
console.warn('no call matches expected args; recorded:', recorded);
} Prevention
- Read the per-call diff in the failure to find the divergent argument.
- Use asymmetric matchers (expect.any, expect.objectContaining) when only part of an argument is significant.
When it happens
Trigger: expect(spy).toHaveBeenCalledWith(arg1, arg2) where no recorded call deep-equals (arg1, arg2); or the negated form where at least one call did match. Uses equalsArgumentArray (jestEquals element-by-element with iterableEquality).
Common situations: Argument shape mismatch — e.g. the code passed an object with extra keys, a string instead of a number, or a different array length. The diff in the message highlights the first divergence per call.
Related errors
- ${formatReturns(spy, results, msg, value)}
- ${msg}
- ${msg} (${stripped} matching ${stripped === 1 ? 'property' :
- ${utils.inspect(assertion._obj)} is not a spy or a call to a
- ${utils.inspect(resultSpy)} is not a spy or a call to a spy
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/7e29d9b6c6168bb6.json.
Report an issue: GitHub.