bun-jest-migration について
JestのテストスイートをBunのテストランナーへ移行する開発者向けのスキルです。APIや設定の対応に加え、モジュールモック、タイマー、スナップショットの移行時の問題を解説します。
主な機能
- 01JestからBunへの移行手順
- 02API互換性のガイド
- 03モックとスパイの置き換え
- 04タイマーとスナップショットの移行
- 05設定変換とエラー対応
活用シーン
- 01テストスイートのJestからBunへの移行
- 02Jestのモックとスパイの置き換え
- 03テスト設定の移行
- 04Bunのテストエラーの調査
インストール
コマンドをコピーしてターミナルで実行します。
$
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() の第 3 引数 |
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 対応