mockについて
モック(mock)について
Section titled “モック(mock)について”テストにおける**モック(mock)**は、実際のオブジェクトの振る舞いを模倣(シミュレート)するために使われる、偽のオブジェクトです。モックを使うことで、依存関係を持つコンポーネントを隔離してテストできます。
モックの目的と使い方
Section titled “モックの目的と使い方”モックの主な目的は、テスト対象のコンポーネントが依存している外部サービスや関数を、テスト実行中に制御可能にすることです。これにより、以下のようなメリットが得られます。
- 分離テスト: データベースや外部APIなど、実際の環境に依存する処理を置き換えることで、ネットワークの遅延や外部サービスのダウンといった影響を受けずに、テスト対象のロジックを単体でテストできます。
- 結果の制御: 外部サービスが返すはずの「特定のデータ」や「エラー」といった結果を、テストのシナリオに合わせて自由に設定できます。これにより、正常系だけでなく、様々なエラーケースやエッジケースのテストも容易になります。
- 高速化: 実際のI/O処理(例:ファイルの読み書き)をスキップするため、テストの実行時間を大幅に短縮できます。
例:Jestでのモックの使い方
Section titled “例:Jestでのモックの使い方”Node.jsのJestフレームワークでは、jest.mock()やjest.fn()を使ってモックを簡単に作成できます。
// 実際の外部APIを呼び出す関数const axios = require('axios');const fetchUserData = async (userId) => { const response = await axios.get(`https://api.example.com/users/${userId}`); return response.data;};
// テストファイルtest('ユーザーデータを正しく取得できること', async () => { // 1. axiosモジュール全体をモック化 jest.mock('axios');
// 2. モックした関数の戻り値を設定 axios.get.mockResolvedValue({ data: { id: 1, name: 'John Doe' } });
// 3. テスト対象の関数を実行 const userData = await fetchUserData(1);
// 4. 検証(モックされた戻り値が使われていることを確認) expect(userData.name).toBe('John Doe'); expect(axios.get).toHaveBeenCalledWith('https://api.example.com/users/1');});この例では、axiosという外部依存をモックすることで、実際のネットワーク通信を行わずにテストを完結させています。mockResolvedValueで成功時の戻り値を、mockRejectedValueで失敗時の戻り値を設定できます。
モック、スタブ、スパイの違い
Section titled “モック、スタブ、スパイの違い”テストにおける似た用語として、モック、スタブ(stub)、スパイ(spy)がありますが、それぞれ異なる役割を持っています。
| 種類 | 目的 | 振る舞い |
|---|---|---|
| スタブ | 関数呼び出しに対する決められた応答(決まった戻り値)を提供する。 | 元の関数を置き換え、テスト用の固定値を返す。 |
| スパイ | 元の関数を実行させつつ、その呼び出し状況(引数、回数など)を記録・検証する。 | 元の関数の振る舞いを維持しながら、呼び出しを監視する。 |
| モック | 偽のオブジェクト全体を作り、メソッド呼び出しとその検証の両方を行う。 | 元の関数を置き換え、テストの意図に合わせた戻り値を返すだけでなく、呼び出しの検証も担う。 |
簡単に言えば、スタブは「この入力を受け取ったら、この出力を返す」というシンプルな役割を、スパイは「この関数が呼び出されたか」という事実を、そしてモックは「この関数がこの引数で呼び出され、この出力を返したか」という包括的な役割を果たします。多くのテストフレームワークでは、これらの機能を区別せず、mockという総称で扱っています。