运行时包管理器打包器测试运行器代码检查格式化指南参考博客反馈

日期和时间

学习如何在你的 Bun 测试中使用 setSystemTime 和 Jest 兼容函数操作时间和日期

bun:test 允许你在测试中更改当前时间。

这适用于以下任意一种情况:

  • Date.now
  • new Date()
  • new Intl.DateTimeFormat().format()。

setSystemTime

要更改系统时间,请使用 setSystemTime:

test.ts
import { setSystemTime, beforeAll, test, expect } from "bun:test";

beforeAll(() => {
  setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
});

test("它是2020年", () => {
  expect(new Date().getFullYear()).toBe(2020);
});

bun:test 也支持 Jest 的 useFakeTimers 和 useRealTimers,因此使用这些函数的现有测试仍可正常运行:

test.ts
test("就像在 jest 中一样", () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
  expect(new Date().getFullYear()).toBe(2020);
  jest.useRealTimers();
  expect(new Date().getFullYear()).toBeGreaterThan(2020);
});

test("与 jest 不同", () => {
  const OriginalDate = Date;
  jest.useFakeTimers();
  if (typeof Bun === "undefined") {
    // 在 Jest 中,Date 构造函数会改变
    // 这可能导致各种错误,因为测试前后 Date !== Date。
    expect(Date).not.toBe(OriginalDate);
    expect(Date.now).not.toBe(OriginalDate.now);
  } else {
    // 在 bun:test 中,使用 useFakeTimers 时 Date 构造函数不会改变
    expect(Date).toBe(OriginalDate);
    expect(Date.now).toBe(OriginalDate.now);
  }
});

重置系统时间

要重置系统时间,请调用 setSystemTime 并不传入参数:

test.ts
import { setSystemTime, expect, test } from "bun:test";

test("曾经是2020年,只有一会儿。", () => {
  // 先设置为某个时间!
  setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
  expect(new Date().getFullYear()).toBe(2020);

  // 重置它!
  setSystemTime();

  expect(new Date().getFullYear()).toBeGreaterThan(2020);
});

使用 jest.now() 获取模拟时间

当时间被模拟时(通过 setSystemTime 或 useFakeTimers),jest.now() 会返回当前模拟的时间戳:

test.ts
import { test, expect, jest } from "bun:test";

test("获取当前模拟时间", () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));

  expect(Date.now()).toBe(1577836800000); // 2020年1月1日的时间戳
  expect(jest.now()).toBe(1577836800000); // 相同的值

  jest.useRealTimers();
});

使用它可以读取模拟时间,而无需创建新的 Date 对象。

设置时区

默认情况下,bun test 在 UTC (Etc/UTC) 时区运行。要更改时区,可以将 TZ 环境变量传递给 bun test:

terminal
TZ=America/Los_Angeles bun test

或者在运行时设置 process.env.TZ:

test.ts
import { test, expect } from "bun:test";

test("欢迎来到加利福尼亚!", () => {
  process.env.TZ = "America/Los_Angeles";
  expect(new Date("2020-07-01T00:00:00.000Z").getTimezoneOffset()).toBe(420);
  expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe("America/Los_Angeles");
});

test("欢迎来到纽约!", () => {
  // 与 Jest 不同,你可以在运行时多次设置时区,并且可以生效。
  process.env.TZ = "America/New_York";
  expect(new Date("2020-07-01T00:00:00.000Z").getTimezoneOffset()).toBe(240);
  expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe("America/New_York");
});