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. 02Jestのモックとスパイの置き換え
  3. 03テスト設定の移行
  4. 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 の互換性

完全に互換性があります
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() の第 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}`
    };
  }
});

手順に沿った移行

  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グローバルの jestbun:test からインポートします
mock.module is not a functionインポートが間違っていますimport { mock } from "bun:test"
Snapshot mismatchシリアライズ方法が異なります--update-snapshots で更新します

参照ドキュメントを読み込むタイミング

次の場合は references/compatibility-matrix.md を読み込みます:

  • Jest API との互換性に関する詳細
  • サポートされていない機能の一覧
  • 不足している機能への回避策

コメント