モックとスタブの違いとは?テストダブルの使い分けを初心者向けに解説

 

テストダブルの基本概念

ソフトウェアテストにおいて、外部依存関係を持つコードをテストする際に使用される代替オブジェクトを「テストダブル」と呼びます。映画撮影におけるスタントダブルのように、実際のオブジェクトの代わりを務める役割を持ちます。

テストダブルの中でも特に混同されやすいのが「モック」と「スタブ」です。両者は似たような場面で使用されるため、その違いを正しく理解することが効果的なテスト設計に不可欠です。

なぜテストダブルが必要なのか

現代のソフトウェア開発では、データベース、外部API、ファイルシステム、ネットワーク通信など、多くの外部依存関係が存在します。これらの依存関係をそのままテストに含めると、以下のような問題が発生します。

テスト実行の不安定性 外部システムの状態やネットワークの状況によって、テスト結果が変動してしまいます。

テスト実行時間の増大 データベースアクセスやネットワーク通信により、テストの実行時間が大幅に増加します。

テスト環境の複雑化 テスト実行のために多くの外部システムを準備・維持する必要が生じます。

スタブ(Stub)の詳細解説

スタブの基本定義

スタブとは、テスト対象のコードが依存する外部コンポーネントの代替として機能する、最小限の実装を持つオブジェクトです。主な目的は、テスト対象のコードに対して予測可能で一貫した応答を提供することです。

スタブの主要特徴

状態ベースの検証 スタブを使用するテストでは、テスト実行後の結果(戻り値や状態変化)を検証します。スタブ自体の呼び出し履歴や回数は通常チェックしません。

シンプルな実装 スタブは必要最小限の機能のみを実装し、複雑なビジネスロジックは含みません。

データの提供に特化 テスト対象のコードが正常に動作するために必要なデータを提供することが主目的です。

スタブの使用場面

データベースアクセスの代替 データベースからのデータ取得をシミュレートし、一貫したテストデータを提供します。

外部APIの代替 外部サービスのAPIレスポンスを模擬し、ネットワーク依存を排除します。

時間依存処理の制御 現在日時を返すシステム関数の代替として、固定の日時を返すスタブを使用します。

モック(Mock)の詳細解説

モックの基本定義

モックとは、テスト対象のコードが依存するオブジェクトの動作を模擬し、さらに期待される相互作用(メソッド呼び出しの回数、順序、引数など)を事前に設定・検証できるオブジェクトです。

モックの主要特徴

相互作用ベースの検証 モックを使用するテストでは、オブジェクト間の相互作用(メソッド呼び出しなど)が期待通りに行われたかを検証します。

期待値の事前設定 テスト実行前に、どのメソッドが何回、どのような引数で呼び出されるかを事前に定義します。

厳密な検証 期待された相互作用と実際の相互作用が一致しない場合、テストは失敗します。

モックの使用場面

副作用のある処理の検証 メール送信、ログ出力、ファイル書き込みなど、副作用を伴う処理の実行確認に使用します。

複雑なオブジェクト間連携の検証 複数のオブジェクトが協調して動作する際の、相互作用パターンの検証に活用します。

セキュリティ機能の検証 認証・認可処理など、正しい手順で実行されることが重要な機能のテストに使用します。

モックとスタブの主要な違い

検証方法の違い

項目 スタブ モック
検証対象 テスト実行後の結果・状態 オブジェクト間の相互作用
検証タイミング テスト実行後 テスト実行中・実行後
関心事 「何が返されたか」 「どのように呼び出されたか」

実装アプローチの違い

スタブのアプローチ テスト対象のコードが必要とするデータや動作を提供することに集中し、その使われ方には関心を持ちません。

モックのアプローチ テスト対象のコードとの相互作用パターンを厳密に定義し、期待通りの呼び出しが行われるかを監視します。

テスト設計への影響

スタブを使用したテスト

  • より柔軟で変更に強い
  • テスト対象の内部実装に依存しにくい
  • 結果重視のテスト設計

モックを使用したテスト

  • より厳密で詳細な検証が可能
  • テスト対象の内部実装に依存しやすい
  • プロセス重視のテスト設計

その他のテストダブルとの関係

フェイク(Fake)

実際のオブジェクトの軽量版実装です。動作する機能を持ちますが、本番では使用できない簡易版として実装されます。

特徴:

  • 実際に動作するビジネスロジックを含む
  • メモリ上のデータベースなどが典型例
  • テスト専用の実装

ダミー(Dummy)

メソッドのシグネチャを満たすためだけに存在し、実際には使用されないオブジェクトです。

特徴:

  • 実装は最小限または空
  • パラメータの埋め合わせが主目的
  • 呼び出されることは想定されない

効果的な使い分けの指針

スタブを選ぶべき場合

結果を重視するテスト 計算結果、変換結果、集計結果など、最終的な出力が正しいかを確認したい場合に適しています。

外部データソースの代替 データベース、ファイル、設定値など、データの取得が主目的の依存関係に対して使用します。

テストの安定性を重視 外部環境の影響を排除し、一貫したテスト結果を得たい場合に効果的です。

モックを選ぶべき場合

相互作用を重視するテスト オブジェクト間の連携パターンや呼び出し順序が重要な場合に使用します。

副作用のある処理のテスト メール送信、ログ記録、監査ログなど、実行されること自体が重要な処理のテストに適しています。

詳細な動作検証が必要 セキュリティ機能や重要なビジネスロジックで、正確な実行手順の確認が必要な場合に使用します。

実装時のベストプラクティス

スタブ実装のポイント

シンプルさの維持 複雑なロジックを含めず、必要最小限の機能に留めることが重要です。

一貫した応答 同じ入力に対して常に同じ応答を返すよう実装し、テストの再現性を確保します。

エラーケースの考慮 正常系だけでなく、例外やエラー状況もシミュレートできるよう設計します。

モック実装のポイント

期待値の明確化 何を、いつ、どのように呼び出されることを期待するかを明確に定義します。

適切な粒度の選択 過度に細かい相互作用まで検証すると、テストが脆くなる可能性があります。

検証の自動化 モックフレームワークを活用し、期待値の設定と検証を自動化します。

よくある誤解と注意点

用語の混同について

「モック」の汎用的使用 実際にはスタブを使用しているにも関わらず、テストダブル全般を「モック」と呼ぶ習慣があります。正確な用語使用により、チーム内での理解を統一しましょう。

過度な使用の問題

スタブの過多 あらゆる依存関係をスタブに置き換えると、実際の統合時に問題が発見されにくくなります。

モックの過多 モックを多用すると、テストがテスト対象の内部実装に過度に依存し、リファクタリング時にテストが失敗しやすくなります。

テスト戦略とのバランス

単体テストと統合テストの役割分担 スタブやモックを使用する単体テストと、実際の依存関係を使用する統合テストを適切に組み合わせることが重要です。

まとめ

モックとスタブは、どちらもテストダブルの重要な種類ですが、その目的と使用方法は明確に異なります。スタブは結果の検証に焦点を当て、モックは相互作用の検証に重点を置いています。

効果的なテスト設計には、テスト対象の特性と検証したい内容に応じて適切なテストダブルを選択することが重要です。両者の特徴を理解し、適切に使い分けることで、より保守しやすく信頼性の高いテストスイートを構築できます。

テスト駆動開発(TDD)や継続的インテグレーション(CI)の実践において、モックとスタブの適切な活用は、開発効率と品質向上の両立を実現する重要な要素となるでしょう。

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<オンライン無料>ゼロから始めるPython爆速講座