bun test 與 Bun 的運行時深度集成。這是使 bun test 快速且易於使用的一部分原因。
環境變量
NODE_ENV
bun test 自動將 $NODE_ENV 設置為 "test",除非它已在環境中或通過 .env 文件設置。這是大多數測試運行器的標准行為,有助於確保一致的測試行為。
import { test, expect } from "bun:test";
test("NODE_ENV 設置為 test", () => {
expect(process.env.NODE_ENV).toBe("test");
});你可以通過顯式設置 NODE_ENV 來覆蓋此設置:
NODE_ENV=development bun testTZ(時區)
默認情況下,所有 bun test 運行都使用 UTC(Etc/UTC)作為時區,除非被 TZ 環境變量覆蓋。這確保了不同開發環境中的日期和時間行為一致。
import { test, expect } from "bun:test";
test("時區默認為 UTC", () => {
const date = new Date();
expect(date.getTimezoneOffset()).toBe(0);
});要使用特定時區進行測試:
TZ=America/New_York bun test測試超時
如果沒有顯式覆蓋,每個測試的默認超時時間為 5000 毫秒(5 秒)。超過此超時的測試將失敗。
全局超時
使用 --timeout 標志全局更改超時:
bun test --timeout 10000 # 10 秒每個測試的超時
將超時設置為測試函數的第三個參數:
import { test, expect } from "bun:test";
test("快速測試", () => {
expect(1 + 1).toBe(2);
}, 1000); // 1 秒超時
test("慢速測試", async () => {
await new Promise(resolve => setTimeout(resolve, 8000));
}, 10000); // 10 秒超時無限超時
使用 0 或 Infinity 禁用超時:
test("無超時測試", async () => {
// 此測試可以無限期運行
await someVeryLongOperation();
}, 0);錯誤處理
未處理的錯誤
bun test 跟蹤未處理的 promise 拒絕和測試之間發生的錯誤。如果發生此類錯誤,最終退出碼將為非零(具體為這些錯誤的數量),即使所有測試都通過。
這有助於捕獲異步代碼中否則可能被忽視的錯誤:
import { test } from "bun:test";
test("測試 1", () => {
// 此測試通過
expect(true).toBe(true);
});
// 此錯誤發生在任何測試之外
setTimeout(() => {
throw new Error("未處理的錯誤");
}, 0);
test("測試 2", () => {
// 此測試也通過
expect(true).toBe(true);
});
# 測試運行仍將失敗,退出碼為非零
# 因為未處理的錯誤Promise 拒絕
未處理的 promise 拒絕也會被捕獲:
import { test } from "bun:test";
test("通過的測試", () => {
expect(1).toBe(1);
});
// 這將導致測試運行失敗
Promise.reject(new Error("未處理的拒絕"));自定義錯誤處理
你可以在測試設置中設置自定義錯誤處理程序:
process.on("uncaughtException", error => {
console.error("未捕獲的異常:", error);
process.exit(1);
});
process.on("unhandledRejection", (reason, promise) => {
console.error("未處理的拒絕:", promise, "原因:", reason);
process.exit(1);
});CLI 標志集成
幾個 Bun CLI 標志可以與 bun test 一起使用以修改其行為:
內存使用
# 減少測試運行器 VM 的內存使用
bun test --smol調試
# 將調試器附加到測試運行器進程
bun test --inspect
bun test --inspect-brk模塊加載
# 在測試文件之前運行腳本(用於全局設置/模擬)
bun test --preload ./setup.ts
# 設置編譯時常量
bun test --define "process.env.API_URL='http://localhost:3000'"
# 配置自定義加載器
bun test --loader .special:special-loader
# 使用不同的 tsconfig
bun test --tsconfig-override ./test-tsconfig.json
# 為模塊解析設置 package.json 條件
bun test --conditions development
# 為測試加載環境變量
bun test --env-file .env.test安裝相關的標志
# 影響測試執行期間的任何網絡請求或自動安裝
bun test --prefer-offline
bun test --frozen-lockfile監視和熱重載
監視模式
使用 --watch 標志運行 bun test 時,測試運行器將監視文件更改並重新運行受影響的測試。
bun test --watch測試運行器很智能地知道要重新運行哪些測試:
import { add } from "./math.js";
import { test, expect } from "bun:test";
test("加法", () => {
expect(add(2, 3)).toBe(5);
});如果你修改 math.js,只有 math.test.ts 將重新運行,而不是所有測試。
熱重載
--hot 標志提供類似的功能,但在嘗試在運行之間保留狀態方面更積極:
bun test --hot對於大多數測試場景,--watch 是推薦的選項,因為它在測試運行之間提供更好的隔離。
全局變量
以下全局變量在測試文件中自動可用,無需導入(但如果願意,也可以從 bun:test 導入):
// 所有這些都可以在全局范圍內使用
test("全局測試函數", () => {
expect(true).toBe(true);
});
describe("全局 describe", () => {
beforeAll(() => {
// 全局 beforeAll
});
it("全局 it 函數", () => {
// it 是 test 的別名
});
});
// Jest 兼容性
jest.fn();
// Vitest 兼容性
vi.fn();如果你願意,也可以顯式導入它們:
import { test, it, describe, expect, beforeAll, beforeEach, afterAll, afterEach, jest, vi } from "bun:test";進程集成
退出碼
bun test 使用標准退出碼:
0:所有測試通過,沒有未處理的錯誤1:測試失敗>1:未處理錯誤的數量(即使測試通過)
信號處理
測試運行器正確處理常見信號:
# 優雅地停止測試執行
kill -SIGTERM <test-process-pid>
# 立即停止測試執行
kill -SIGKILL <test-process-pid>環境檢測
Bun 自動檢測某些環境並調整行為:
// GitHub Actions 檢測
if (process.env.GITHUB_ACTIONS) {
// Bun 自動發出 GitHub Actions 注解
}
// CI 檢測
if (process.env.CI) {
// 某些行為可能會針對 CI 環境進行調整
}性能考慮
單進程
測試運行器默認在單個進程中運行所有測試。這提供:
- 更快的啟動 - 無需生成多個進程
- 共享內存 - 高效的資源使用
- 簡單的調試 - 所有測試在一個進程中
然而,這意味著:
- 測試共享全局狀態(使用生命周期鉤子清理)
- 一個測試崩潰可能影響其他測試
- 沒有真正的單個測試並行化
內存管理
# 監控內存使用
bun test --smol # 減少內存佔用
# 對於大型測試套件,考慮拆分文件
bun test src/unit/
bun test src/integration/測試隔離
由於測試在同一進程中運行,請確保正確清理:
import { afterEach } from "bun:test";
afterEach(() => {
// 清理全局狀態
global.myGlobalVar = undefined;
delete process.env.TEST_VAR;
// 如有需要重置模塊
jest.resetModules();
});