mcpField
B
bun-jest-migration

bun-jest-migration

github.com/secondsky测试与质量240392 次安装5 周前更新
代码仓库

关于 bun-jest-migration

帮助开发者将 Jest 测试套件迁移到 Bun 测试运行器的技能,涵盖常用 API 和配置对照,并说明模块模拟、计时器与快照等迁移问题。

主要功能

  1. 01Jest 到 Bun 的迁移步骤
  2. 02API 兼容性指引
  3. 03模拟与间谍函数转换
  4. 04计时器和快照迁移
  5. 05配置转换与错误排查

适用场景

  1. 01将测试套件从 Jest 迁至 Bun
  2. 02替换 Jest 模拟与间谍函数
  3. 03迁移测试配置
  4. 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 兼容性

完全兼容
JestBun备注
describe()describe()完全相同
it() / test()test()使用 test()
expect()expect()匹配器相同
beforeAll/EachbeforeAll/Each完全相同
afterAll/EachafterAll/Each完全相同
jest.fn()mock()使用 mock()
jest.spyOn()spyOn()完全相同
需要修改
JestBun 对应项
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}`
    };
  }
});

分步迁移

  1. 移除 Jest 包

    bun remove jest ts-jest @types/jest babel-jest jest-environment-jsdom
    
  2. 更新 package.json

    {
      "scripts": {
        "test": "bun test",
        "test:watch": "bun test --watch",
        "test:coverage": "bun test --coverage"
      }
    }
    
  3. 将 jest.config.js 转换为 bunfig.toml

  4. 更新测试文件中的导入

    • 查找并替换 @jest/globals → bun:test
    • 查找并替换 jest.fn() → mock()
    • 查找并替换 jest.mock() → mock.module()
  5. 运行并修复

    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