关于 bun-jest-migration
帮助开发者将 Jest 测试套件迁移到 Bun 测试运行器的技能,涵盖常用 API 和配置对照,并说明模块模拟、计时器与快照等迁移问题。
主要功能
- 01Jest 到 Bun 的迁移步骤
- 02API 兼容性指引
- 03模拟与间谍函数转换
- 04计时器和快照迁移
- 05配置转换与错误排查
适用场景
- 01将测试套件从 Jest 迁至 Bun
- 02替换 Jest 模拟与间谍函数
- 03迁移测试配置
- 04排查 Bun 测试错误
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill bun-jest-migration安装后在 Claude Code 中输入/bun-jest-migration确认已加载。
详细介绍
Bun Jest 迁移
Bun 的测试运行器兼容 Jest。大多数 Jest 测试无需修改即可运行。
快速迁移
# 1. Remove Jest dependencies
bun remove jest ts-jest @types/jest babel-jest
# 2. Update test script
# package.json: "test": "bun test"
# 3. Run tests
bun test
导入变更
// Before (Jest)
import { describe, it, expect, jest } from '@jest/globals';
// After (Bun) - No import needed, or explicit:
import { describe, test, expect, mock, spyOn } from "bun:test";
API 兼容性
完全兼容
| Jest | Bun | 备注 |
|---|---|---|
describe() | describe() | 完全相同 |
it() / test() | test() | 使用 test() |
expect() | expect() | 匹配器相同 |
beforeAll/Each | beforeAll/Each | 完全相同 |
afterAll/Each | afterAll/Each | 完全相同 |
jest.fn() | mock() | 使用 mock() |
jest.spyOn() | spyOn() | 完全相同 |
需要修改
| Jest | Bun 对应项 |
|---|---|
jest.mock('module') | mock.module('module', () => {...}) |
jest.useFakeTimers() | import { setSystemTime } from "bun:test" |
jest.setTimeout() | test() 的第三个参数 |
jest.clearAllMocks() | 对每个模拟调用 .mockClear() |
模拟迁移
模拟函数
// Jest
const fn = jest.fn().mockReturnValue('value');
// Bun
const fn = mock(() => 'value');
// Or for compatibility:
import { jest } from "bun:test";
const fn = jest.fn(() => 'value');
模块模拟
// Jest (top-level hoisting)
jest.mock('./utils', () => ({
helper: jest.fn(() => 'mocked')
}));
// Bun (inline, no hoisting)
import { mock } from "bun:test";
mock.module('./utils', () => ({
helper: mock(() => 'mocked')
}));
间谍迁移
// Jest
jest.spyOn(console, 'log').mockImplementation(() => {});
// Bun (identical)
spyOn(console, 'log').mockImplementation(() => {});
定时器迁移
// Jest
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-01-01'));
jest.advanceTimersByTime(1000);
// Bun - supports Jest-compatible timer APIs
import { setSystemTime } from "bun:test";
import { jest } from "bun:test";
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-01-01'));
jest.advanceTimersByTime(1000); // Now supported
快照测试
// Jest
expect(component).toMatchSnapshot();
expect(data).toMatchInlineSnapshot(`"expected"`);
// Bun (identical)
expect(component).toMatchSnapshot();
expect(data).toMatchInlineSnapshot(`"expected"`);
更新快照:
bun test --update-snapshots
配置迁移
jest.config.js → bunfig.toml
// jest.config.js (before)
module.exports = {
testMatch: ['**/*.test.ts'],
testTimeout: 10000,
setupFilesAfterEnv: ['./jest.setup.ts'],
collectCoverage: true,
coverageThreshold: { global: { lines: 80 } }
};
# bunfig.toml (after)
[test]
root = "./"
preload = ["./jest.setup.ts"]
timeout = 10000
coverage = true
coverageThreshold = 0.8
常见迁移问题
问题:jest.mock 不起作用
// Jest mock hoisting doesn't exist in Bun
// Move mock.module before imports or use dynamic imports
// Solution 1: Use mock.module at top
mock.module('./api', () => ({ fetch: mock() }));
import { fetch } from './api';
// Solution 2: Dynamic import
const mockFetch = mock();
mock.module('./api', () => ({ fetch: mockFetch }));
const { fetch } = await import('./api');
问题:缺少定时器函数
// Bun timer support is limited
// Use setSystemTime for date mocking
import { setSystemTime } from "bun:test";
beforeEach(() => {
setSystemTime(new Date('2024-01-01'));
});
afterEach(() => {
setSystemTime(); // Reset to real time
});
问题:自定义匹配器
// Jest
expect.extend({ toBeWithinRange(received, floor, ceiling) {...} });
// Bun (same API)
import { expect } from "bun:test";
expect.extend({
toBeWithinRange(received, floor, ceiling) {
const pass = received >= floor && received <= ceiling;
return {
pass,
message: () => `expected ${received} to be within ${floor}-${ceiling}`
};
}
});
分步迁移
-
移除 Jest 包
bun remove jest ts-jest @types/jest babel-jest jest-environment-jsdom -
更新 package.json
{ "scripts": { "test": "bun test", "test:watch": "bun test --watch", "test:coverage": "bun test --coverage" } } -
将 jest.config.js 转换为 bunfig.toml
-
更新测试文件中的导入
- 查找并替换
@jest/globals→bun:test - 查找并替换
jest.fn()→mock() - 查找并替换
jest.mock()→mock.module()
- 查找并替换
-
运行并修复
bun test 2>&1 | head -50 # Check first errors
常见错误
| 错误 | 原因 | 修复方法 |
|---|---|---|
Cannot find module '@jest/globals' | 旧导入 | 使用 bun:test |
jest is not defined | 全局 jest | 从 bun:test 导入 |
mock.module is not a function | 导入错误 | import { mock } from "bun:test" |
Snapshot mismatch | 序列化方式不同 | 使用 --update-snapshots 更新 |
何时加载参考资料
遇到以下情况时,加载 references/compatibility-matrix.md:
- 需要完整了解 Jest API 兼容性详情
- 需要查看不支持的功能列表
- 需要查找缺失功能的变通方法
评论
支持 Markdown