mcpField
B
bun-test-mocking

bun-test-mocking

github.com/secondskyテスト・品質240412 回インストール5 週間前に更新
リポジトリ

bun-test-mocking について

Bunでテストを行う開発者向けのモック機能のスキルです。関数やメソッド、モジュールのモックと、呼び出しの検証方法を扱います。

主な機能

  1. 01モック関数と戻り値の設定
  2. 02関数の実装の置き換え
  3. 03オブジェクトメソッドのスパイ
  4. 04モジュールとNodeモジュールのモック
  5. 05呼び出し情報と結果の確認

活用シーン

  1. 01非同期関数に一度限りの戻り値を設定
  2. 02メソッドの呼び出し回数と引数を検証
  3. 03テスト中に依存モジュールを分離

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/secondsky/claude-skills --skill bun-test-mocking

インストール後、Claude Code で/bun-test-mockingを入力して読み込まれたか確認します。

詳細

Bun テストのモック

Bun では、mock()、spyOn()、モジュールのモックを使って、Jest 互換のモックを利用できます。

モック関数

import { test, expect, mock } from "bun:test";

// Create mock function
const fn = mock(() => "original");

test("mock function", () => {
  fn("arg1", "arg2");

  expect(fn).toHaveBeenCalled();
  expect(fn).toHaveBeenCalledTimes(1);
  expect(fn).toHaveBeenCalledWith("arg1", "arg2");
});
jest.fn() との互換性
import { test, expect, jest } from "bun:test";

const fn = jest.fn(() => "value");

test("jest.fn works", () => {
  const result = fn();
  expect(result).toBe("value");
  expect(fn).toHaveBeenCalled();
});

モックの戻り値

const fn = mock();

// Return value once
fn.mockReturnValueOnce("first");
fn.mockReturnValueOnce("second");

// Permanent return value
fn.mockReturnValue("default");

// Promise returns
fn.mockResolvedValue("resolved");
fn.mockResolvedValueOnce("once");
fn.mockRejectedValue(new Error("fail"));
fn.mockRejectedValueOnce(new Error("once"));

モックの実装

const fn = mock();

// Set implementation
fn.mockImplementation((x) => x * 2);

// One-time implementation
fn.mockImplementationOnce((x) => x * 10);

// Chain implementations
fn
  .mockImplementationOnce(() => "first")
  .mockImplementationOnce(() => "second")
  .mockImplementation(() => "default");

メソッドをスパイする

import { test, expect, spyOn } from "bun:test";

const obj = {
  method: () => "original",
};

test("spy on method", () => {
  const spy = spyOn(obj, "method");

  obj.method();

  expect(spy).toHaveBeenCalled();
  expect(obj.method()).toBe("original"); // Still works

  // Override implementation
  spy.mockImplementation(() => "mocked");
  expect(obj.method()).toBe("mocked");

  // Restore
  spy.mockRestore();
  expect(obj.method()).toBe("original");
});

モジュールのモック

import { test, expect, mock } from "bun:test";

// Mock entire module
mock.module("./utils", () => ({
  add: mock(() => 999),
  subtract: mock(() => 0),
}));

// Now imports use mocked version
import { add } from "./utils";

test("mocked module", () => {
  expect(add(1, 2)).toBe(999);
});
Node モジュールのモック
mock.module("axios", () => ({
  default: {
    get: mock(() => Promise.resolve({ data: "mocked" })),
    post: mock(() => Promise.resolve({ data: "created" })),
  },
}));
ファクトリーを使ったモック
mock.module("./config", () => {
  return {
    API_URL: "http://test.local",
    DEBUG: true,
  };
});

モックのアサーション

const fn = mock();

fn("a", "b");
fn("c", "d");

// Call count
expect(fn).toHaveBeenCalled();
expect(fn).toHaveBeenCalledTimes(2);

// Call arguments
expect(fn).toHaveBeenCalledWith("a", "b");
expect(fn).toHaveBeenLastCalledWith("c", "d");
expect(fn).toHaveBeenNthCalledWith(1, "a", "b");

// Return values
fn.mockReturnValue("result");
fn();
expect(fn).toHaveReturned();
expect(fn).toHaveReturnedWith("result");
expect(fn).toHaveReturnedTimes(1);

モックのプロパティ

const fn = mock(() => "value");

fn("arg1");
fn("arg2");

// Access call info
fn.mock.calls;        // [["arg1"], ["arg2"]]
fn.mock.results;      // [{ type: "return", value: "value" }, ...]
fn.mock.lastCall;     // ["arg2"]

// Clear history
fn.mockClear();       // Clear calls, keep implementation
fn.mockReset();       // Clear calls + implementation
fn.mockRestore();     // Restore original (for spies)

よくあるパターン

Fetch のモック
import { test, expect, spyOn } from "bun:test";

test("mock fetch", async () => {
  const spy = spyOn(global, "fetch").mockResolvedValue(
    new Response(JSON.stringify({ data: "mocked" }))
  );

  const response = await fetch("/api/data");
  const json = await response.json();

  expect(json.data).toBe("mocked");
  expect(spy).toHaveBeenCalledWith("/api/data");

  spy.mockRestore();
});
Console のモック
test("mock console", () => {
  const spy = spyOn(console, "log");

  console.log("test message");

  expect(spy).toHaveBeenCalledWith("test message");
  spy.mockRestore();
});
クラスメソッドのモック
class UserService {
  async getUser(id: string) {
    // Real implementation
  }
}

test("mock class method", () => {
  const service = new UserService();
  const spy = spyOn(service, "getUser").mockResolvedValue({
    id: "1",
    name: "Test User",
  });

  const user = await service.getUser("1");

  expect(user.name).toBe("Test User");
  expect(spy).toHaveBeenCalledWith("1");
});

よくあるエラー

エラー原因修正方法
Cannot spy on undefinedプロパティが存在しませんプロパティ名を確認してください
Not a function関数ではないものをモックしようとしています適切なモック方法を使用してください
Already mocked二重にモックしています先に mockRestore を使用してください
Module not foundモジュールのパスが間違っていますmock.module 内のパスを確認してください

リファレンスを読み込むタイミング

次の場合は references/mock-api.md を読み込んでください:

  • モック/スパイ API の完全なリファレンスが必要な場合
  • 高度なモックのパターンを確認する場合

次の場合は references/module-mocking.md を読み込んでください:

  • 複雑なモジュールのモックを行う場合
  • ホイスティングの動作の詳細を確認する場合

コメント