CTS-KB

テストダブル

てすとだぶる

Test Double モック スタブ スパイ Mock Stub Spy Fake Dummy
#テスト #テスト技法 #単体テスト

テスト時に本物のオブジェクトの代わりに使う「替え玉」の総称。Gerard Meszaros が『xUnit Test Patterns』で 5 種類に体系化した。Stub・Mock・Spy・Fake・Dummy を用途で使い分ける。

概要

単体テスト では、対象を外部依存(DB・API・時刻・乱数)から切り離す必要がある。このとき本物の代わりに テストダブル を使う。「ダブル(double)」は映画の代役(スタントダブル)と同じ意味。

5 種類のテストダブル

種類役割いつ使うか
Stub決め打ちの値を返すだけテスト対象が「読み取る」依存先
Mock呼び出された事実を 検証するテスト対象が「書き込む」依存先で、呼び出しの正しさを検証
Spy呼び出しを記録するだけ(事後検証)Mock より柔軟に、後から呼び出し履歴を確認
Fake簡易実装(インメモリ DB 等)本物に近い振る舞いが必要、保守性重視
Dummy引数を埋めるためだけ引数として渡す必要があるが、実際には使われない

Stub の例

// テスト対象が getUser(123) を呼ぶ → 固定値を返す
const userStub = {
  findById: (id) => ({ id: 123, name: "山田太郎" })
}

// テスト対象を実行
const result = orderService.createOrder(userStub, ...)

// 結果を検証(Stub 自体は検証しない)
expect(result.customerName).toBe("山田太郎")

Mock の例

// 「save が 1 回呼ばれた」ことを検証する
const orderRepoMock = jest.fn()
orderService.save(orderRepoMock, order)

// 呼び出された事実を検証
expect(orderRepoMock).toHaveBeenCalledWith(order)
expect(orderRepoMock).toHaveBeenCalledTimes(1)

Mock vs Spy の違い

MockSpy
期待値を 事前 に書く(厳格)呼び出しを記録、 事後 に検証(柔軟)
期待外の呼び出しは即失敗テスト終了時に確認
振る舞いを強制観察するだけ

Fake が一番強い

観点Mock / StubFake
本物への忠実度低(事前ハードコード)高(簡易実装で振る舞う)
API 変更への追従全テスト書き直しFake 1 箇所修正で済む
AI 駆動開発との相性

リポジトリパターンIOrderRepository を切り、 InMemoryOrderRepository を Fake として実装 すれば、DB 起動なしで業務ロジックを単体テストできる。AI ループが秒で回る理想形。

アンチパターン

失敗起きること
Mock 一辺倒API 変更で全テストが壊れる、メンテ地獄
Mock 過剰「テストは通るが本物では壊れる」状態に
全部 Fakeテスト対象 vs Fake で、本物のバグを検出できない
内部実装に Spy を当てるリファクタで全テスト壊れる、内部結合

指針: 境界(DB・外部 API)だけ Mock、内部は Fake、副作用検証は Spy、決め打ち入力は Stub。

AI 駆動開発との関係

AI に「テスト書いて」と指示すると、 モック一辺倒 で書きがち。次のように指示すると保守性が上がる:

テストダブルの方針:
  - DB アクセスは InMemoryOrderRepository (Fake) を使う
  - 外部 API は MSW でモック
  - 副作用の検証は Spy で「呼ばれた事実」だけを確認
  - 内部メソッドは Mock しない

関連記事

関連用語