TaskBuild spy() returning a function with .calls = [] and .returnValue. Calling the spy pushes args to .calls and returns .returnValue. Set s.returnValue = 42, call s('a', 'b') twice, log s.calls.length, s.calls[0].join(','), s('x') === 42.
Spies — recording calls
150 XP10 min
Theory
When you need to know how a function called its dependencies
A spy is a fake function that records every call and lets you assert on them later.
function spy() {
const fn = function (...args) {
fn.calls.push(args);
return fn.returnValue;
};
fn.calls = [];
fn.returnValue = undefined;
return fn;
}Usage:
const onSave = spy(); onSave.returnValue = "ok"; processForm(formData, onSave); assert(onSave.calls.length === 1, "save called once"); assertEqual(onSave.calls[0][0].name, "Anna", "first arg was formData");
Why this is enough
Vitest's vi.fn() and Jest's jest.fn() are this exact shape with bells (.mockImplementation, .mockReturnValueOnce, .mockResolvedValue). For 80% of tests, a vanilla spy is plenty.
🔒
Sign up to start coding
Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial — card required, cancel anytime.
Sign up — free trial →First 10 lessons in each track are free. No card needed for those.