Sinon
02 / 02

Cleanup, Fake Timers & Testing Tradeoffs

Cleanup, Fake Timers & Testing Tradeoffs

Restoring & Sandboxes

const sandbox = sinon.createSandbox()

afterEach(() => {
  sandbox.restore() // restores every fake created via sandbox.stub/spy/mock
})

it('does something', () => {
  const stub = sandbox.stub(db, 'query').resolves([])
  // ...
})

Failing to restore a stub on a shared object is a classic source of test pollution — the fake behavior can leak into and break later, unrelated tests. Sandboxes group multiple fakes so a single afterEach restore() call cleans them all up reliably.

Fake Timers

const clock = sinon.useFakeTimers(new Date('2026-01-01'))

scheduleReminder() // internally uses setTimeout
clock.tick(60 * 60 * 1000) // advance 1 hour instantly
sinon.assert.calledOnce(reminderCallback)

clock.restore()

useFakeTimers replaces setTimeout, setInterval, and Date with controllable fakes — tests advance simulated time instantly and deterministically instead of waiting on real delays or depending on the actual current time, eliminating a whole class of flaky, timing-dependent test failures.

createStubInstance & sinon.fake

createStubInstance(SomeClass) produces a fake with every method pre-stubbed, avoiding manual per-method setup for class-shaped dependencies. The newer sinon.fake() API offers a more minimal alternative for common faking needs without the full spy/stub/mock surface.

The Overuse Tradeoff

Stubbing an external dependency (database, HTTP call) makes unit tests fast, deterministic, and independent of network/database availability. But excessive mocking can couple tests tightly to implementation details and hide real integration bugs that only appear when components actually interact — worth balancing with some integration/end-to-end coverage that exercises real interactions.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free