# fake-timers: a clock you control instead of waiting

> The fake-timers package gives you setTimeout, setImmediate, setInterval, requestAnimationFrame and requestIdleCallback, plus Date, performance and nextTick, all driven by a clock instance you advance by hand. It exists so a test can assert on something that happens fifteen milliseconds from now without spending fifteen milliseconds.

**sinonjs/fake-timers** — Fake setTimeout and friends (collectively known as "timers"). Useful in your JavaScript tests. Extracted from Sinon.JS

- Repository: https://github.com/sinonjs/fake-timers
- Stars: 860 · Forks: 128
- Language: JavaScript
- License: BSD-3-Clause
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/sinonjs-fake-timers

## A clock, and the APIs that read from it

The package is a JavaScript implementation of the timer APIs: setTimeout, clearTimeout, setImmediate, clearImmediate, setInterval, clearInterval, requestAnimationFrame, cancelAnimationFrame, requestIdleCallback and cancelIdleCallback, along with a clock instance that controls the flow of time. FakeTimers also provides a Date implementation that gets its time from the clock. The environment decides what else comes along: in a browser environment the package provides a performance implementation that gets its time from the clock, and in Node environments it provides a nextTick implementation synchronised with the clock and a process.hrtime shim that works with the clock. That list is the real scope of the package, and it is wider than most people assume, since animation frames and idle callbacks are the ones a UI test needs and the ones people usually forget.

## Creating a clock and moving it forward

To use the package you create a clock, schedule events on it with the timer functions, and pass time with the tick method.

```js
var FakeTimers = require("@sinonjs/fake-timers");
var clock = FakeTimers.createClock();

clock.setTimeout(function () {
    console.log(
        "The poblano is a mild chili pepper originating in the state of Puebla, Mexico.",
    );
}, 15);

clock.tick(15);
```

The last line prints the fact synchronously to the screen. If you want to simulate asynchronous behaviour there are async variants of the same functions, for example clock.tick(time) against await clock.tickAsync(time), and the next, runAll, runToFrame and runToLast methods are available to advance the clock. The distinction between the two variants of tick is the single most common source of confusion with this package, because a test that awaits a promise inside a timer needs the asynchronous variant or the promise never resolves.

## install replaces the native timers, uninstall puts them back

When you are testing timers you will usually want to replace the native timers so that calling setTimeout actually schedules a callback with your clock instance rather than with the browser's internals. Calling install with no arguments achieves this, and you can call uninstall later to restore things as they were. Note that in NodeJS the timers and timers/promises modules also receive fake timers when using global scope.

```js
var FakeTimers = require("@sinonjs/fake-timers");

var clock = FakeTimers.install();

setTimeout(fn, 15); // Schedules with clock.setTimeout

clock.uninstall();
// setTimeout is restored to the native implementation
```

To hijack timers in another context you pass it to the install method, using withGlobal to wrap a context object whose setTimeout is the global one by default. Usually you want to install the timers onto the global object, so call install without arguments.

## Advancing time automatically when you do not know when to tick

Sometimes you do not know when to call tick, because the code under test advances time on its own. FakeTimers supports attaching the faked timers to any change in the real system time, so there is no need to tick the clock in that situation. This is achieved using the original setImmediate API at a certain configurable interval, config.advanceTimeDelta, whose default is 20ms, which means time is incremented every 20ms rather than in real time.

```js
var FakeTimers = require("@sinonjs/fake-timers");
var clock = FakeTimers.install({
    shouldAdvanceTime: true,
    advanceTimeDelta: 40,
});

setTimeout(() => {
    console.log("this just timed out");
}, 30);

setImmediate(() => {
    console.log("not so immediate");
});

setTimeout(() => {
    console.log("this timed out after");
    clock.uninstall();
}, 50);
```

In addition, mocked time can be configured to advance more quickly using clock.setTickMode with a mode of nextAsync, where the clock advances to the first scheduled timer and fires it, in a loop, breaking the event loop between each timer so that scheduled promise callbacks execute before the next one runs.

## The clock API and the epoch you start from

The API reference documents createClock with an optional now and loopLimit. The default epoch is 0, and the now argument may be a number in milliseconds, a Date object, a Temporal.Instant or a Temporal.ZonedDateTime. The loopLimit argument sets the maximum number of timers that will be run when calling runAll before the library assumes it has an infinite loop and throws an error, with the default at 1000. The epoch default is worth pausing on, because it means Date now reads 1970 unless you say otherwise, and a test that compares a formatted timestamp against today's date will fail in a way that looks like a timezone bug. The loop limit is the other setting to know, because a recursive timer under test will otherwise hang the suite until the runner gives up.

## It ships its own type definitions

The package ships built-in type definitions generated from JSDoc, which provides autocomplete and type suggestions in supporting IDEs and TypeScript projects without requiring external @types packages. That is a small thing that matters in practice, because the older generation of timer fakes usually meant installing a separate DefinitelyTyped package that lagged behind the implementation. The repository shows how the types are produced and checked: there are scripts for types:build and types:check using a dedicated tsconfig.types.json, a types:smoke target that compiles two consumer projects, one with a DOM and one without, and a posttest hook that runs the type build so a broken declaration fails the test run rather than being noticed later. There is also a types directory at the repository root and a separate tsconfig.types.json for the build.

## How the package is tested

The test scripts tell you what the project cares about. The Node suite is mocha with a two second timeout, running both the unit tests and the integration tests, with a dot reporter and a check-leaks flag that fails the run if a test leaves a global behind. That last flag is the direct answer to the failure mode this package creates, since a fake timer that is never uninstalled poisons everything after it. The browser tests run through mochify driving Puppeteer, and the cloud scripts drive Microsoft Edge, Firefox and Safari through the same harness with a shared mochify.webdriver.js configuration. Coverage is measured with nyc, and the release process is a set of shell scripts under scripts for preversion, version and postversion, with husky preparing the git hooks. The default test script runs the Node suite and then the headless browser one.

## Where fake-timers is the wrong choice

Four limits apply. It only knows the APIs it fakes, so a library that reads the real system clock directly will disagree with the fake Date, and that disagreement is a class of bug that is hard to trace. The asynchronous semantics are the second limit: the synchronous tick fires callbacks but does not let promise continuations run, which is why the async variant exists, and picking the wrong one produces a test that hangs rather than one that fails clearly. Third, a leaked fake timer is a global mutation that outlives the test that created it, so the package relies on discipline and on the leak check in the Node suite rather than on making the mistake impossible. And fourth, this is the extracted timer half of Sinon.JS, not a general mocking library: if you need to stub a network call or replace a module, that is the other package, and the two are used together rather than interchangeably.

## Conclusion

Use fake-timers when a test depends on time passing, because a clock you tick by hand turns a fifteen second timeout into an instant assertion and makes the test deterministic rather than slow. Do not use it to fake time your production code depends on in a way the library does not model, since the clock only knows the APIs it fakes and anything reading the real system time directly will disagree with it. Verify first which environment you are in, because the browser build fakes performance while the Node build fakes nextTick and process.hrtime, that you pick the synchronous or the async variant of tick deliberately, since tickAsync exists to let promise callbacks run, and that you always uninstall the clock, since a leaked fake timer will silently break every later test in the same file.

## FAQ

### What does the @sinonjs/fake-timers package provide?

A JavaScript implementation of the timer APIs, including setTimeout, clearTimeout, setImmediate, clearImmediate, setInterval, clearInterval, requestAnimationFrame, cancelAnimationFrame, requestIdleCallback and cancelIdleCallback, plus a Date implementation that gets its time from the clock, a performance implementation in browsers, and a nextTick implementation and process.hrtime shim in Node.

### How do I install fake-timers and use it?

Run npm install @sinonjs/fake-timers, then create a clock with FakeTimers.createClock(), schedule a callback with clock.setTimeout, and advance time with clock.tick. To replace the native globals instead, call FakeTimers.install() and later clock.uninstall() to restore them.

### What is the difference between tick and tickAsync?

The synchronous tick fires scheduled callbacks without letting promise continuations run, while the async variant awaits and lets promise callbacks execute before the next timer fires. A test that awaits a promise inside a timer needs the asynchronous form or the promise never resolves.

### Can fake-timers advance time on its own?

Yes. Installing with shouldAdvanceTime set to true attaches the faked timers to changes in the real system time, so you do not need to tick the clock yourself. The advanceTimeDelta option sets the interval, defaulting to 20ms, and time is incremented at that interval rather than in real time.

### Does fake-timers include TypeScript types?

Yes. The package ships built-in type definitions generated from JSDoc, giving autocomplete and type suggestions in supporting IDEs and TypeScript projects without needing an external @types package, and the repository has build, check and smoke scripts for the type definitions.

## Sources

- [Issues](https://github.com/sinonjs/fake-timers/issues)
- [License: BSD-3-Clause](https://github.com/sinonjs/fake-timers/blob/main/LICENSE)
- [README](https://github.com/sinonjs/fake-timers/blob/main/README.md)
- [Releases](https://github.com/sinonjs/fake-timers/releases)
- [sinonjs/fake-timers on GitHub](https://github.com/sinonjs/fake-timers)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sinonjs-fake-timers
