第40回: モックとスタブ — 外部依存を「テスト用の替え玉」に差し替える

章: 第5章: テストと品質管理

テストを実行するたびにDBへアクセスしたり、外部APIを呼び出したりしていませんか?

外部依存が絡むテストは遅く・不安定で・副作用が生じます。モックとスタブを使えば、テスト中に依存クラスを「替え玉」に差し替えて、速くて安定したテストを書けます。

外部依存に直接依存するテストで何が起きるか

DBが空でテストが失敗する・APIのレートリミットに引っかかる・ネットワーク障害でCIが落ちる。こうした問題はモックを使って依存を差し替えることで解消できます。

モック・スタブの使い分け

種類 用途 特徴
スタブ 戻り値を固定する メソッドが返す値を制御する
モック 呼び出しを検証する 「何回・どの引数で呼ばれたか」を確認する
フェイク 簡易的な実装で動作させる Queue::fake() / Event::fake() など
スパイ 呼び出し記録を後で検証する モックの後検証版

チェックポイント: createMock() で生成したモックは、指定していないメソッドを呼ぶと例外を投げます。テスト対象のコードが呼ぶすべてのメソッドにスタブを設定するか、createStub() を使いましょう。過剰なモックはテストがコードの実装に密結合してしまうサインです。

コードサンプル


<?php
use PHPUnit\Framework\TestCase;
class OrderServiceTest extends TestCase {
    public function test_find_calls_repository(): void {
        $repo = $this->createMock(OrderRepository::class);
        $repo->expects($this->once())
             ->method('findById')
             ->with(1)
             ->willReturn(new Order(1));
        $service = new OrderService($repo);
        $order = $service->find(1);
        $this->assertSame(1, $order->id);
    }
}

まとめ & 次のステップ

  • モックとスタブで外部依存を差し替えると、テストが速く・安定します
  • createMock() で自動的に全メソッドをオーバーライドしたモックを生成できます
  • expects($this->once()) でメソッドが1回だけ呼ばれることを検証できます
  • Laravelの Queue::fake() / Mail::fake() はフェイクとして機能します
  • 過剰なモックはリファクタリング時にテストが壊れやすくなるため、公開インターフェースに絞りましょう

次回は テスト駆動開発(TDD)入門 を学びます。テストを先に書くことで設計と実装を同時に整える手法を整理しましょう。

Related Articles