> For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt.

# Fake timers

当你的代码中设置了很长的定时器（timeout），而你又不想在测试中等待它们时，fake timers 会非常有用。

Rstest 提供了一些实用函数，基于 [@sinonjs/fake-timers](https://github.com/sinonjs/fake-timers) 实现定时器的模拟。

## rs.useFakeTimers

- **别名：** `rstest.useFakeTimers`
- **类型：** `(config?: FakeTimerInstallOpts) => RstestUtilities & Disposable`

调用此方法可以启用定时器的模拟。底层使用 [@sinonjs/fake-timers](https://github.com/sinonjs/fake-timers)。

- **示例：**

```ts
rs.useFakeTimers();
```

你也可以传递配置对象以自定义 fake timers 的行为。

该配置会透传给 `@sinonjs/fake-timers`。例如，`toFake` 和 `toNotFake` 用于控制要模拟哪些定时器 API，`now` 用于设置初始的模拟系统时间，`shouldAdvanceTime` / `advanceTimeDelta` 用于开启自动推进。

- **`using` 语法**


[Added in v0.10.3](https://github.com/web-infra-dev/rstest/releases/tag/v0.10.3)

`rs.useFakeTimers()` 返回一个 `Disposable`，可配合 `using` 语法在代码块退出时自动恢复真实定时器。

`_timers` 变量以下划线开头，表示它不会被直接使用。`using` 语法要求声明一个变量，因此不能省略 `_timers`，但可以使用其他变量名。

```ts
{
  using _timers = rs.useFakeTimers();
  // Fake timers 在这个代码块中启用。
}

// 真实定时器已恢复。
```

## rs.useRealTimers

- **别名：** `rstest.useRealTimers`
- **类型：** `() => RstestUtilities`

恢复原生的定时器函数（如 `setTimeout`、`setInterval` 等），关闭 fake timers。

```ts
rs.useRealTimers();
```

## rs.isFakeTimers

- **别名：** `rstest.isFakeTimers`
- **类型：** `() => boolean`

如果当前启用了 fake timers，则返回 `true`，否则返回 `false`。

```ts
if (rs.isFakeTimers()) {
  // Fake timers 已启用
}
```

## rs.setSystemTime

- **别名：** `rstest.setSystemTime`
- **类型：** `(now?: number | Date | { epochMilliseconds: number }) => RstestUtilities`

设置 fake timers 使用的当前系统时间。适用于需要测试依赖当前日期或时间的代码。

启用 fake timers 时，该方法会模拟用户修改系统时钟（影响 `Date`、`performance.now` 等与日期相关的 API），但不会触发任何 timer。若未启用 fake timers，则仅 mock `Date.*` 调用，因此无需先调用 [`rs.useFakeTimers`](#rsusefaketimers) 即可固定时钟。

`now` 也可以是类似 Temporal 的对象，例如 `Temporal.Instant` 或 `Temporal.ZonedDateTime`。

```ts
rs.setSystemTime(new Date('2020-01-01T00:00:00Z'));

expect(new Date().toISOString()).toBe('2020-01-01T00:00:00.000Z');

rs.useRealTimers();
```

## rs.getRealSystemTime

- **别名：** `rstest.getRealSystemTime`
- **类型：** `() => number`

即使在启用 fake timers 时，也可以返回真实系统时间（时间戳）。

```ts
const realTime = rs.getRealSystemTime();
```

## rs.getRealTimers


[Added in v0.11.1](https://github.com/web-infra-dev/rstest/releases/tag/v0.11.1)

- **别名：** `rstest.getRealTimers`
- **类型：** `() => { setTimeout: typeof globalThis.setTimeout; clearTimeout: typeof globalThis.clearTimeout; setImmediate?: typeof globalThis.setImmediate }`

即使在启用 fake timers 时，也可以返回由 Rstest 捕获的真实定时器函数。

```ts
const { setTimeout, clearTimeout } = rs.getRealTimers();

const timeout = setTimeout(() => {
  // 这个定时器使用真实时间。
}, 1000);

clearTimeout(timeout);
```

## rs.runAllTicks

- **别名：** `rstest.runAllTicks`
- **类型：** `() => RstestUtilities`

运行所有已排队的微任务（如 `process.nextTick`）。

## rs.runAllTimers

- **别名：** `rstest.runAllTimers`
- **类型：** `() => RstestUtilities`

执行所有待运行的定时器（包括 timeout 和 interval）。

## rs.runAllTimersAsync

- **别名：** `rstest.runAllTimersAsync`
- **类型：** `() => Promise<RstestUtilities>`

异步执行所有待运行的定时器。

## rs.runOnlyPendingTimers

- **别名：** `rstest.runOnlyPendingTimers`
- **类型：** `() => RstestUtilities`

只运行当前待运行的定时器（不会调度新的定时器）。

## rs.runOnlyPendingTimersAsync

- **别名：** `rstest.runOnlyPendingTimersAsync`
- **类型：** `() => Promise<RstestUtilities>`

异步只运行当前待运行的定时器。

## rs.advanceTimersByTime

- **别名：** `rstest.advanceTimersByTime`
- **类型：** `(ms: number | string | Temporal.Duration) => RstestUtilities`

将 fake timers 快进指定的毫秒数，并执行在此期间计划的所有定时器。

字符串时长使用与 `@sinonjs/fake-timers` 相同的格式，例如 `'00:10'` 表示 10 秒。

## rs.advanceTimersByTimeAsync

- **别名：** `rstest.advanceTimersByTimeAsync`
- **类型：** `(ms: number | string | Temporal.Duration) => Promise<RstestUtilities>`

异步快进 fake timers 指定的毫秒数。

## rs.advanceTimersToNextTimer

- **别名：** `rstest.advanceTimersToNextTimer`
- **类型：** `(steps?: number) => RstestUtilities`

将定时器推进到下一个计划的定时器，可选地指定推进的步数。

## rs.advanceTimersToNextTimerAsync

- **别名：** `rstest.advanceTimersToNextTimerAsync`
- **类型：** `(steps?: number) => Promise<RstestUtilities>`

异步将定时器推进到下一个计划的定时器。

## rs.advanceTimersToNextFrame

- **别名：** `rstest.advanceTimersToNextFrame`
- **类型：** `() => RstestUtilities`

将定时器推进到下一个动画帧。

## rs.jumpTimersByTime


[Added in v0.11.0](https://github.com/web-infra-dev/rstest/releases/tag/v0.11.0)

- **别名：** `rstest.jumpTimersByTime`
- **类型：** `(ms: number | string | Temporal.Duration) => RstestUtilities`

将模拟时钟直接跳过指定时间，每个受影响的定时器回调最多只会触发一次。它适用于模拟 JavaScript 引擎被挂起后恢复的场景，此时中间的 interval tick 会被跳过。

```ts
rs.useFakeTimers({ now: 0 });

const cb = rs.fn();
setInterval(cb, 1000);

rs.jumpTimersByTime(5000);

expect(cb).toHaveBeenCalledTimes(1);
```

## rs.setTickMode


[Added in v0.11.0](https://github.com/web-infra-dev/rstest/releases/tag/v0.11.0)

- **别名：** `rstest.setTickMode`
- **类型：** `(mode: { mode: 'manual' | 'nextAsync' } | { mode: 'interval'; delta?: number }) => RstestUtilities`

配置 fake timers 自动推进时间的方式。

- `{ mode: 'manual' }`：只有调用 `rs.advanceTimersByTime()` 等 API 时，定时器才会推进。
- `{ mode: 'nextAsync' }`：时钟会持续推进到下一个计划的定时器，并在定时器之间让 Promise 回调运行。
- `{ mode: 'interval', delta?: number }`：按间隔推进模拟时间，等价于 `shouldAdvanceTime` / `advanceTimeDelta`。

```ts
rs.useFakeTimers();
rs.setTickMode({ mode: 'nextAsync' });

await new Promise((resolve) => setTimeout(resolve, 1000));
```

## rs.getTimerCount

- **别名：** `rstest.getTimerCount`
- **类型：** `() => number`

返回当前 fake timers 中还剩多少个待运行的定时器。

```ts
const count = rs.getTimerCount();
```

## rs.clearAllTimers

- **别名：** `rstest.clearAllTimers`
- **类型：** `() => RstestUtilities`

移除所有已计划但尚未执行的定时器。

```ts
rs.clearAllTimers();
```
