Deterministic timer tests in Jasmine with jasmine.clock()
jasmine.clock().install() replaces native setTimeout, setInterval and Date with a controllable fake clock. Advance virtual time with clock.tick(ms) to test timer-dependent code synchronously, then uninstall to restore natives and avoid spec leakage.
12 Apr 2026, 20:40 UTC

Use jasmine.clock() to make timer-dependent code testable without real waits
The useful answer is: install a fake clock, run code that schedules timers, then advance virtual time with clock.tick(ms) and assert synchronously. jasmine.clock().install() replaces the native setTimeout, setInterval and Date with controllable fakes so tests stay fast and repeatable. Uninstall after each spec to restore native timers and avoid leakage.
Worked spec pattern with install, tick, uninstall
The pattern is per-spec isolation. Install in beforeEach, schedule work inside the spec, tick the exact amount of virtual time needed, assert, then uninstall in afterEach.
describe('debounce with jasmine.clock', () => {
let clock;
let calls;
beforeEach(() => {
clock = jasmine.clock();
clock.install();
calls = [];
});
afterEach(() => {
clock.uninstall();
});
it('fires once after the delay', () => {
const run = () => calls.push(Date.now());
setTimeout(run, 100);
expect(calls.length).toBe(0);
clock.tick(99);
expect(calls.length).toBe(0);
clock.tick(1);
expect(calls.length).toBe(1);
});
});
Where to run: in a Jasmine 3.x/4.x runner for browser or Node. No special permissions are required. The risk is leaving the fake clock installed: subsequent specs will use the fake timers and can fail or hang. Always pair install with uninstall.
What the fake clock actually controls
- setTimeout and setInterval are replaced after install. Timers scheduled before install are not controlled.
- Date is faked. Date.now() and new Date() advance only when you call clock.tick().
- clock.tick(ms) moves virtual time forward synchronously and fires any timers whose due time is reached. It does not wait in real time.
- clock.mockDate(date) can set an initial Date value for the fake clock.
Limits that cause flaky tests
The fake clock does not simulate real async work. It only controls the timer APIs it replaces.
- Timers created before jasmine.clock().install() are not captured. Install before code under test schedules work.
- Microtasks and Promise jobs are not advanced by clock.tick(). Code that uses setTimeout to schedule a Promise resolution will still need the microtask queue to flush.
- setInterval requires repeated ticks. One tick of 1000ms fires an interval once; to fire three times you need three ticks or a larger tick that covers multiple intervals.
- performance.now and requestAnimationFrame are not mocked by default. Code using those APIs will see real time and tests can appear flaky.
- Real I/O, network, or timers from other libraries are not simulated.
Practical check: create a minimal spec that installs the clock, schedules a setTimeout, calls clock.tick with less than the delay and asserts the callback has not run, then tick the remaining ms and assert it has run. This demonstrates deterministic control.
Common mistakes and how to avoid them
Forgetting uninstall
If afterEach does not call clock.uninstall(), the next spec inherits the fake timers. Symptoms are timers never firing or Date being stuck. Keep install/uninstall in the same describe block and prefer per-spec over suite-wide install.
Ticking too far
clock.tick(10000) will fire all pending timers up to 10 seconds, including ones you did not intend to test. Tick the smallest amount needed and assert intermediate states.
Mixing done callbacks with fake clock
Jasmine async done callbacks rely on real time to complete. With a fake clock, the spec can finish before the done callback is called, leading to timeouts. Use synchronous assertions with clock.tick instead of done when testing timers.
Installing after scheduling
Calling jasmine.clock().install() after the system under test already called setTimeout means that timer is bound to the real clock. Install before exercising the code.
Version note: jasmine.clock() API surface is stable in Jasmine 3.x and 4.x, but availability differs between runners. Verify install/uninstall exist in your runner and avoid global suite installation to keep failures reproducible.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.