Create a Spy Function (Test Double)

intermediate
By FrontendAtlas Editorial · Updated Oct 10, 2026
Implement createSpy(impl?) to produce a callable spy that records every call (args + this) and optionally delegates to an implementation. Spies are a core unit-testing tool to verify behavior at boundaries (network, storage, analytics) without needing a full mocking library.

Arguments

  • impl: Function (optional) — Optional implementation to call. The spy must preserve the caller's this value.

Returns

Function — A spy function with metadata: calls, thisValues, callCount(), lastCall(), reset().

Solution idea

A spy is just a function with extra state. Record calls in arrays, and if an implementation is provided, delegate to it using apply() so this binding is preserved.

Examples
const spy = createSpy((a, b) => a + b);
spy(1, 2); // => 3
spy.calls; // => [[1, 2]]
spy.callCount(); // => 1

const obj = { x: 2, fn: createSpy(function (n) { return this.x + n; }) };
obj.fn(3); // => 5 (this preserved)
obj.fn.thisValues[0] === obj; // true