npx skills add https://github.com/daleseo/bun-skills --skill bun-test使用与 Jest 兼容的 API 设置 Bun 内置的测试运行器,执行速度显著更快(比 Jest 快 3-10 倍)。
有关详细模式,请参阅:
# 验证 Bun 安装
bun --version
# 检查项目是否存在
ls -la package.json
询问用户需要什么类型的测试:
# 创建测试目录
mkdir -p tests/{unit,integration,fixtures}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
推荐的结构:
project/
├── src/
│ ├── utils.ts
│ └── components/
├── tests/
│ ├── unit/ # 单元测试
│ ├── integration/ # 集成测试
│ ├── fixtures/ # 测试数据
│ └── setup.ts # 全局设置
├── package.json
└── bunfig.toml # 测试配置
在项目根目录创建 bunfig.toml:
[test]
# 运行测试前预加载文件
preload = ["./tests/setup.ts"]
# 代码覆盖率
coverage = true
coverageDir = "coverage"
coverageThreshold = 80
# 超时设置(毫秒)
timeout = 5000
# 首次失败后停止
bail = false
创建 tests/setup.ts:
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
// 全局测试设置
beforeAll(() => {
console.log("🧪 开始测试套件");
process.env.NODE_ENV = "test";
});
afterAll(() => {
console.log("✅ 测试套件完成");
});
// 每个测试前重置模拟
beforeEach(() => {
// 清除模拟状态
});
afterEach(() => {
// 每个测试后清理
});
// 全局测试工具
globalThis.testHelpers = {
wait: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
};
创建 tests/unit/example.test.ts:
import { describe, it, expect, test } from "bun:test";
// 简单测试
test("加法有效", () => {
expect(1 + 1).toBe(2);
});
// 使用描述块组织测试
describe("数组工具", () => {
it("应该过滤偶数", () => {
const numbers = [1, 2, 3, 4, 5, 6];
const evens = numbers.filter(n => n % 2 === 0);
expect(evens).toEqual([2, 4, 6]);
expect(evens).toHaveLength(3);
});
});
// 异步测试
describe("异步操作", () => {
it("应该处理 Promise", async () => {
const result = await Promise.resolve(42);
expect(result).toBe(42);
});
});
更多测试示例(API 测试、数据库测试等),请参阅 examples.md。
import { describe, it, expect, mock, spyOn } from "bun:test";
describe("模拟函数", () => {
it("应该创建模拟函数", () => {
const mockFn = mock((x: number) => x * 2);
const result = mockFn(5);
expect(result).toBe(10);
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toHaveBeenCalledWith(5);
});
it("应该监视方法", () => {
const obj = {
method: (x: number) => x * 2,
};
const spy = spyOn(obj, "method");
obj.method(5);
expect(spy).toHaveBeenCalledWith(5);
expect(spy).toHaveReturnedWith(10);
});
});
高级模拟模式,请参阅 mocking.md。
添加测试脚本:
{
"scripts": {
"test": "bun test",
"test:watch": "bun test --watch",
"test:coverage": "bun test --coverage",
"test:ui": "bun test --coverage --reporter=html"
}
}
# 运行所有测试
bun test
# 运行特定文件
bun test tests/unit/utils.test.ts
# 监视模式
bun test --watch
# 带覆盖率
bun test --coverage
# 按名称过滤
bun test --test-name-pattern="should handle"
如果从 Jest 迁移,请参阅 jest-migration.md 了解:
@jest/globals → bun:test)jest.fn() → mock())关键更改:
// 之前 (Jest)
import { describe, it, expect } from '@jest/globals';
const mockFn = jest.fn();
// 之后 (Bun)
import { describe, it, expect, mock } from 'bun:test';
const mockFn = mock();
import { test, expect } from "bun:test";
function add(a: number, b: number): number {
return a + b;
}
test("add 函数", () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
test("应该抛出错误", () => {
const throwError = () => {
throw new Error("出错了");
};
expect(throwError).toThrow("出错了");
expect(throwError).toThrow(Error);
});
test("应该拒绝 Promise", async () => {
const asyncReject = async () => {
throw new Error("异步错误");
};
await expect(asyncReject()).rejects.toThrow("异步错误");
});
test("应该匹配快照", () => {
const data = {
id: 1,
name: "测试用户",
email: "test@example.com",
};
expect(data).toMatchSnapshot();
});
test("应该匹配内联快照", () => {
const config = { theme: "dark", language: "en" };
expect(config).toMatchInlineSnapshot(`
{
"theme": "dark",
"language": "en"
}
`);
});
可用的常见匹配器:
// 相等性
expect(value).toBe(expected); // ===
expect(value).toEqual(expected); // 深度相等
// 真值性
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeDefined();
expect(value).toBeUndefined();
// 数字
expect(number).toBeGreaterThan(3);
expect(number).toBeLessThan(5);
// 字符串
expect(string).toMatch(/pattern/);
expect(string).toContain("substring");
// 数组
expect(array).toContain(item);
expect(array).toHaveLength(3);
// 对象
expect(object).toHaveProperty("key");
expect(object).toMatchObject({ subset });
// Promise
await expect(promise).resolves.toBe(value);
await expect(promise).rejects.toThrow();
// 模拟函数
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(3);
expect(mockFn).toHaveBeenCalledWith(arg1, arg2);
import { beforeAll, afterAll, beforeEach, afterEach, describe, it } from "bun:test";
describe("用户服务", () => {
let db: Database;
beforeAll(async () => {
// 所有测试前的设置
db = await connectToDatabase();
});
afterAll(async () => {
// 所有测试后的清理
await db.close();
});
beforeEach(async () => {
// 每个测试前重置
await db.clear();
});
it("应该创建用户", async () => {
const user = await db.users.create({ name: "测试" });
expect(user.id).toBeDefined();
});
});
查看覆盖率报告:
# 生成覆盖率
bun test --coverage
# 查看 HTML 报告
bun test --coverage --reporter=html
open coverage/index.html
在 bunfig.toml 中设置覆盖率阈值:
[test]
coverage = true
coverageThreshold = 80 # 如果覆盖率 < 80% 则失败
# 使用调试器运行
bun test --inspect
# 详细输出
bun test --verbose
# 显示所有测试结果
bun test --reporter=tap
Bun 测试比 Jest 快得多:
执行速度快 3-10 倍!
基本设置完成后:
详细实现,请参阅上面链接的参考文件。
每周安装次数
76
代码仓库
GitHub 星标数
3
首次出现
2026年1月26日
安全审计
安装于
opencode65
codex59
gemini-cli58
github-copilot55
cursor51
kimi-cli47
Set up Bun's built-in test runner with Jest-compatible APIs and significantly faster execution (3-10x faster than Jest).
For detailed patterns, see:
# Verify Bun installation
bun --version
# Check if project exists
ls -la package.json
Ask the user what type of testing they need:
# Create test directories
mkdir -p tests/{unit,integration,fixtures}
Recommended structure:
project/
├── src/
│ ├── utils.ts
│ └── components/
├── tests/
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ ├── fixtures/ # Test data
│ └── setup.ts # Global setup
├── package.json
└── bunfig.toml # Test configuration
Create bunfig.toml in project root:
[test]
# Preload files before running tests
preload = ["./tests/setup.ts"]
# Code coverage
coverage = true
coverageDir = "coverage"
coverageThreshold = 80
# Timeouts (in milliseconds)
timeout = 5000
# Bail after first failure
bail = false
Create tests/setup.ts:
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
// Global test setup
beforeAll(() => {
console.log("🧪 Starting test suite");
process.env.NODE_ENV = "test";
});
afterAll(() => {
console.log("✅ Test suite complete");
});
// Reset mocks before each test
beforeEach(() => {
// Clear mock state
});
afterEach(() => {
// Cleanup after each test
});
// Global test utilities
globalThis.testHelpers = {
wait: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
};
Create tests/unit/example.test.ts:
import { describe, it, expect, test } from "bun:test";
// Simple test
test("addition works", () => {
expect(1 + 1).toBe(2);
});
// Describe blocks for organization
describe("Array utilities", () => {
it("should filter even numbers", () => {
const numbers = [1, 2, 3, 4, 5, 6];
const evens = numbers.filter(n => n % 2 === 0);
expect(evens).toEqual([2, 4, 6]);
expect(evens).toHaveLength(3);
});
});
// Async tests
describe("Async operations", () => {
it("should handle promises", async () => {
const result = await Promise.resolve(42);
expect(result).toBe(42);
});
});
For more test examples (API testing, database testing, etc.), see examples.md.
import { describe, it, expect, mock, spyOn } from "bun:test";
describe("Mock functions", () => {
it("should create mock functions", () => {
const mockFn = mock((x: number) => x * 2);
const result = mockFn(5);
expect(result).toBe(10);
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toHaveBeenCalledWith(5);
});
it("should spy on methods", () => {
const obj = {
method: (x: number) => x * 2,
};
const spy = spyOn(obj, "method");
obj.method(5);
expect(spy).toHaveBeenCalledWith(5);
expect(spy).toHaveReturnedWith(10);
});
});
For advanced mocking patterns, see mocking.md.
Add test scripts:
{
"scripts": {
"test": "bun test",
"test:watch": "bun test --watch",
"test:coverage": "bun test --coverage",
"test:ui": "bun test --coverage --reporter=html"
}
}
# Run all tests
bun test
# Run specific file
bun test tests/unit/utils.test.ts
# Watch mode
bun test --watch
# With coverage
bun test --coverage
# Filter by name
bun test --test-name-pattern="should handle"
If migrating from Jest, see jest-migration.md for:
@jest/globals → bun:test)jest.fn() → mock())Key changes:
// Before (Jest)
import { describe, it, expect } from '@jest/globals';
const mockFn = jest.fn();
// After (Bun)
import { describe, it, expect, mock } from 'bun:test';
const mockFn = mock();
import { test, expect } from "bun:test";
function add(a: number, b: number): number {
return a + b;
}
test("add function", () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
test("should throw errors", () => {
const throwError = () => {
throw new Error("Something went wrong");
};
expect(throwError).toThrow("Something went wrong");
expect(throwError).toThrow(Error);
});
test("should reject promises", async () => {
const asyncReject = async () => {
throw new Error("Async error");
};
await expect(asyncReject()).rejects.toThrow("Async error");
});
test("should match snapshot", () => {
const data = {
id: 1,
name: "Test User",
email: "test@example.com",
};
expect(data).toMatchSnapshot();
});
test("should match inline snapshot", () => {
const config = { theme: "dark", language: "en" };
expect(config).toMatchInlineSnapshot(`
{
"theme": "dark",
"language": "en"
}
`);
});
Common matchers available:
// Equality
expect(value).toBe(expected); // ===
expect(value).toEqual(expected); // Deep equality
// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeDefined();
expect(value).toBeUndefined();
// Numbers
expect(number).toBeGreaterThan(3);
expect(number).toBeLessThan(5);
// Strings
expect(string).toMatch(/pattern/);
expect(string).toContain("substring");
// Arrays
expect(array).toContain(item);
expect(array).toHaveLength(3);
// Objects
expect(object).toHaveProperty("key");
expect(object).toMatchObject({ subset });
// Promises
await expect(promise).resolves.toBe(value);
await expect(promise).rejects.toThrow();
// Mock functions
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(3);
expect(mockFn).toHaveBeenCalledWith(arg1, arg2);
import { beforeAll, afterAll, beforeEach, afterEach, describe, it } from "bun:test";
describe("User service", () => {
let db: Database;
beforeAll(async () => {
// Setup before all tests
db = await connectToDatabase();
});
afterAll(async () => {
// Cleanup after all tests
await db.close();
});
beforeEach(async () => {
// Reset before each test
await db.clear();
});
it("should create user", async () => {
const user = await db.users.create({ name: "Test" });
expect(user.id).toBeDefined();
});
});
View coverage report:
# Generate coverage
bun test --coverage
# View HTML report
bun test --coverage --reporter=html
open coverage/index.html
Set coverage thresholds in bunfig.toml:
[test]
coverage = true
coverageThreshold = 80 # Fail if coverage < 80%
# Run with debugger
bun test --inspect
# Verbose output
bun test --verbose
# Show all test results
bun test --reporter=tap
Bun test is significantly faster than Jest:
3-10x faster execution!
After basic setup:
For detailed implementations, see the reference files linked above.
Weekly Installs
76
Repository
GitHub Stars
3
First Seen
Jan 26, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykPass
Installed on
opencode65
codex59
gemini-cli58
github-copilot55
cursor51
kimi-cli47
Vue 3 调试指南:解决响应式、计算属性与监听器常见错误
11,800 周安装
feature-delivery by api/git - 高效功能交付与Git集成工具,提升开发流程自动化
3 周安装
Base链.basename.eth域名注册教程 - 智能体钱包名称注册完整指南
3 周安装
Bankr Club NFT 空投技能 - 每日按比例分发代币给持有者 | 代理代币对齐
3 周安装
智能体安全技能 - 保护AI代理机密信息与交易安全的最佳实践
3 周安装
Bug 闪电战:AI 代理并行修复代码缺陷,自动化 bug 解决流程
4 周安装
ElysiaJS DDD 架构指南:使用 Prisma 和 Better Auth 构建可扩展后端 API
4 周安装