この記事は Calendar for WHITEPLUS | Advent Calendar 2022 - Qiita の8日目の記事です。
こんにちは、ホワイトプラス エンジニアの山内です。
この記事ではテストコードに関連する概念の一つであるmock(モック)とは何かについて自分が理解するまでの過程を紹介したいと思います。
もともと自分にとってモックとは「テストする対象の一部を別のものに置き換えるもの」というフワッとした認識でした。
何故フワッとした認識になっていたのか振り返ってみると 『モックという言葉が別の言葉で頻繁に修飾されているから』 ということが分かりました。
例)
- サンプルコードの説明に「モック(スタブ)」と記述されている
- モック化と書かれているにも関わらず変数名がspyになっている
- 「モックフレームワークの目的はテストダブルの作成」と記述されている
上記よりモックには色々な意味合いが含まれているらしく、このままでは命名時や人とのコミュニケーションが必要な場面で正しく使い分けることが出来ないため調べてみることにしました。
ただ調べていくと、いきなりモックを理解する前にどうやら「テストダブル」という概念を知る必要がありそうでした。
テストダブルとは
テストダブル とは、ソフトウェアテストにおいて、テスト対象が依存しているコンポーネントを置き換える代用品のこと。(wikiより引用)
処理の一部を代用品に置き換えたいケースとは
- テストを実行する上で制約がある場合
- 『テスト環境では正常に実行できない処理』に依存している
- DBに対してUPDATE・INSERTを行っており、実際に処理を走らせたくない
- テスト対象が依存しているコンポーネントの振る舞いを自由に制御したい場合
- 外部APIが特定の例外を返すケースをテストしたい
- 処理が既定の回数呼ばれているかテストしたい
ここまでで下記のことが分かりました。
- 自分がモックの説明として認識していたものは実はテストダブルという別の概念であるということ
- テストダブルは「テストを実行する上で制約がある」or「依存している処理の振る舞いを自由に制御したい」の2種類のケースで主に利用されること
では今まで知ったかぶりで口にしていた「モック」という言葉は何だったんでしょうか
テストダブルに以下のような説明が続いていました。
xUnit Test Patternsによるとテストダブルには以下の5つのパターンが存在します。 それぞれ別の用途で使用され、これらのパターンの総称をテストダブルといいます。
- テストスタブ
- モックオブジェクト
- テストスパイ
- フェイクオブジェクト
- ダミーオブジェクト
ここで元々知りたかったモックとはモックオブジェクトのことで、それはテストダブルのパターンの一つということが分かりました(xUnit Test Patternsに基づく場合)
モックオブジェクトとは
モックオブジェクトとは間接出力の期待値を保持し実際の間接出力の値と比較し成功・失敗をテストコードに返却することができるオブジェクトのことを指します。
また間接出力とはテストコードからは確認できないテスト対象の出力です
public functoin テスト対象() { // テスト対象が依存しているコンポーネントに対して引数 $argumentを出力している 依存しているコンポーネント($argument); }
以下は上記を踏まえて作成したMockeryを使ったサンプルコードです
public function テスト() { // 依存しているコンポーネントの引数に100が入ることを期待 $expect = 100; $mock = Mockery::mock("テスト対象のクラス"); $mock ->shouldReceive("依存しているコンポーネント") // 引数に100が入る場合の設定 ->with($expect) ->andReturn(true); // テストを実行 $this->assertTrue($mock->テスト対象()); } public function テスト対象() { ... $value = 依存しているコンポーネント($argument); ... } public function 依存しているコンポーネント(int $argument) { return 外部APIか何かと通信(); }
※ここでは便宜的に間接入力(テスト対象に対しての入力)の値を判別することで間接出力の期待値を比較しています(他にもっと良い確認方法があるかもしれない)
つまり、テスト対象の中で呼ばれているメソッドの引数に意図した値を出力できているか比較し、その結果を返却するものをモックオブジェクトと呼ぶようです。 ようやくスッキリしました。
フレームワークの名前にMockが含まれていたり、モックオブジェクト自体がスタブの機能を包含していたりと綺麗な切り分けができないことが混同する要因になっていたことが分かりました。
今後は ・テスト対象が依存しているコンポーネントを置き換える代用品 => テストダブル ・間接入力の期待値と実測値を比較してくれる代用品 => モックオブジェクト というニュアンスで言葉を選んで使用していきたいと思います。
- 参考記事
さいごに
ホワイトプラスでは、ビジョンやバリューに共感していただけるエンジニアを募集しています!
ネットクリーニングの「リネット」など「生活領域×テクノロジー」で事業を展開している会社です。 どんな会社か気になった方はオウンドメディア「ホワプラSTYLE」をぜひご覧ください。 オンラインでカジュアル面談もできますので、ぜひお気軽にお問い合わせください。