> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/zhcndoc/bun/llms.txt
> Use this file to discover all available pages before exploring further.

# Fake Timers

> Mock time and timers for deterministic tests

Bun provides fake timers to control time-based operations in your tests. This lets you test timeout, interval, and time-dependent code without waiting for real time to pass.

## Basic usage

Use `jest.useFakeTimers()` to enable fake timers:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("setTimeout with fake timers", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn();
  setTimeout(callback, 1000);
  
  // No time has passed yet
  expect(callback).not.toHaveBeenCalled();
  
  // Fast-forward 1 second
  jest.advanceTimersByTime(1000);
  
  expect(callback).toHaveBeenCalled();
});
```

## Timer APIs

### jest.useFakeTimers()

Enables fake timers. All timer APIs will be mocked:

* `setTimeout`
* `setInterval`
* `setImmediate`
* `Date.now()`
* `new Date()`

```ts theme={null}
import { jest } from "bun:test";

jest.useFakeTimers();
```

### jest.useRealTimers()

Restores real timers:

```ts theme={null}
import { jest } from "bun:test";

jest.useFakeTimers();
// ... tests with fake timers
jest.useRealTimers();
// ... tests with real timers
```

### jest.advanceTimersByTime(ms)

Advances all timers by the specified milliseconds:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("advance timers", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn();
  setTimeout(callback, 1000);
  
  jest.advanceTimersByTime(500);
  expect(callback).not.toHaveBeenCalled();
  
  jest.advanceTimersByTime(500);
  expect(callback).toHaveBeenCalled();
});
```

### jest.runAllTimers()

Runs all pending timers until there are no more:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("run all timers", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn();
  setTimeout(callback, 1000);
  setTimeout(callback, 2000);
  
  jest.runAllTimers();
  
  expect(callback).toHaveBeenCalledTimes(2);
});
```

<Warning>
  `runAllTimers()` will cause an infinite loop if you have recurring timers (like `setInterval`).
</Warning>

### jest.runOnlyPendingTimers()

Runs only the timers that are currently pending:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("run only pending timers", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn(() => {
    // This creates a new timer
    setTimeout(callback, 1000);
  });
  
  setTimeout(callback, 1000);
  
  // Runs only the first timer, not the one created in the callback
  jest.runOnlyPendingTimers();
  
  expect(callback).toHaveBeenCalledTimes(1);
});
```

### jest.advanceTimersToNextTimer()

Advances timers to the next timer:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("advance to next timer", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn();
  setTimeout(callback, 100);
  setTimeout(callback, 200);
  
  jest.advanceTimersToNextTimer();
  expect(callback).toHaveBeenCalledTimes(1);
  
  jest.advanceTimersToNextTimer();
  expect(callback).toHaveBeenCalledTimes(2);
});
```

### jest.clearAllTimers()

Clears all pending timers:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("clear all timers", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn();
  setTimeout(callback, 1000);
  
  jest.clearAllTimers();
  jest.runAllTimers();
  
  expect(callback).not.toHaveBeenCalled();
});
```

### jest.getTimerCount()

Returns the number of pending timers:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("get timer count", () => {
  jest.useFakeTimers();
  
  setTimeout(() => {}, 1000);
  setTimeout(() => {}, 2000);
  
  expect(jest.getTimerCount()).toBe(2);
  
  jest.advanceTimersToNextTimer();
  expect(jest.getTimerCount()).toBe(1);
});
```

## Mocking Date

Fake timers also mock `Date`:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("mock Date", () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date("2024-01-01"));
  
  expect(Date.now()).toBe(new Date("2024-01-01").getTime());
  expect(new Date().toISOString()).toBe("2024-01-01T00:00:00.000Z");
  
  jest.advanceTimersByTime(1000);
  expect(Date.now()).toBe(new Date("2024-01-01").getTime() + 1000);
});
```

### jest.setSystemTime()

Sets the system time:

```ts theme={null}
import { jest } from "bun:test";

jest.useFakeTimers();
jest.setSystemTime(new Date("2024-01-01"));
```

You can also pass a timestamp:

```ts theme={null}
jest.setSystemTime(1704067200000);
```

### jest.getRealSystemTime()

Gets the real system time (even with fake timers enabled):

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("get real system time", () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date("2024-01-01"));
  
  expect(Date.now()).toBe(new Date("2024-01-01").getTime());
  expect(jest.getRealSystemTime()).toBeGreaterThan(new Date("2024-01-01").getTime());
});
```

## Testing intervals

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("setInterval", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn();
  setInterval(callback, 1000);
  
  jest.advanceTimersByTime(2500);
  
  expect(callback).toHaveBeenCalledTimes(2);
  
  jest.advanceTimersByTime(1000);
  expect(callback).toHaveBeenCalledTimes(3);
});
```

## Testing animations

Test `requestAnimationFrame`:

```ts theme={null}
import { test, expect, jest } from "bun:test";

test("requestAnimationFrame", () => {
  jest.useFakeTimers();
  
  const callback = jest.fn();
  requestAnimationFrame(callback);
  
  // Advance by one frame (typically 16ms)
  jest.advanceTimersByTime(16);
  
  expect(callback).toHaveBeenCalled();
});
```

## Cleanup

Always restore real timers after tests:

```ts theme={null}
import { afterEach, jest } from "bun:test";

afterEach(() => {
  jest.useRealTimers();
});
```

Or use `beforeEach` and `afterEach`:

```ts theme={null}
import { beforeEach, afterEach, jest } from "bun:test";

beforeEach(() => {
  jest.useFakeTimers();
});

afterEach(() => {
  jest.useRealTimers();
});
```

## Real-world example

Testing a debounce function:

```ts theme={null}
import { test, expect, jest, beforeEach, afterEach } from "bun:test";

function debounce(fn: Function, delay: number) {
  let timeoutId: Timer;
  return (...args: any[]) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn(...args), delay);
  };
}

beforeEach(() => {
  jest.useFakeTimers();
});

afterEach(() => {
  jest.useRealTimers();
});

test("debounce delays execution", () => {
  const callback = jest.fn();
  const debounced = debounce(callback, 1000);
  
  debounced("arg1");
  expect(callback).not.toHaveBeenCalled();
  
  jest.advanceTimersByTime(999);
  expect(callback).not.toHaveBeenCalled();
  
  jest.advanceTimersByTime(1);
  expect(callback).toHaveBeenCalledWith("arg1");
});

test("debounce cancels previous calls", () => {
  const callback = jest.fn();
  const debounced = debounce(callback, 1000);
  
  debounced("arg1");
  jest.advanceTimersByTime(500);
  
  debounced("arg2");
  jest.advanceTimersByTime(500);
  
  // First call was cancelled
  expect(callback).not.toHaveBeenCalled();
  
  jest.advanceTimersByTime(500);
  expect(callback).toHaveBeenCalledTimes(1);
  expect(callback).toHaveBeenCalledWith("arg2");
});
```

## Vitest compatibility

Bun also supports Vitest's timer APIs:

```ts theme={null}
import { vi } from "bun:test";

vi.useFakeTimers();
vi.advanceTimersByTime(1000);
vi.runAllTimers();
vi.useRealTimers();
```

All `jest.*` timer methods are available as `vi.*` as well.

## Related

* [Mocks](/test/mocks)
* [Writing Tests](/test/writing)
* [Lifecycle Hooks](/test/lifecycle)
