BIOGRAPHYREADME2015.10.12Laravelでアプリケーションテストをする際のモックの話このブログははてなブログからの移行記事です。アプリケーションテスト要するに結合テストのことです。Laravelでの単体テストは基本的にPHPUnitとLaravelによるヘルパーメソッドを使用することで楽に書けます。アプリケーションテストもまた、ヘルパーが用意されており直感的に書くことができると個人的に思っています。Laravelしかしながらアプリケーションテストを書く際に少しばかり躓いたのでそれをサービスコンテナによって凌いだお話をします。あるページであるデータが表示されてほしい表題のようなテストを書くとします。}}</div>@endforeachコントローラーメソッドがこんな感じ。id="user">が表示されることで担保するのであれば以下のようなテストで確かめることができます。id="user">');}簡単ですね!しかしモデルメソッドの実装が複雑だとちと困ったことになります。ここに複雑なモデルメソッドがあるじゃろ?前述の$this->userModel->getUsers()の実装が例えばこうなっているとします。JOINし、それらのフラグも見た上でユーザをとっています。この時、アプリケーションテストをする時の問題に以下のようなものがあります。DBを叩く処理が走るのでテスト用DBを用意しなければならないしかもテスト毎に同じ環境を作らなければいけないテスト用データを作る際、getUsers()で1つ以上のデータが返ってくるようなデータを作らなければいけないこんなん、規模がでかくなって走るモデルメソッドの数が増えたらあっという間につらくなります。モックというソリューションこうなると当然、UserModelのgetUsers()をモック化する発想にいたります。単体テストでUserModelに依存しているクラスをテストするのであればコンストラクターにモックを渡すことでメソッド内のUserModelの振る舞いを制御することが可能です。これはアプリケーションテスト。この時のUserModelを一体どうやってモックに差し替えるんだ?リクエストに何かデータを持たせてそれをコントローラーから受け取れるようにしてそれでサービスクラスにそれを渡させてそれを見て逐一モックに切り替えるのそれともああああああああって僕はなりました。人類に結合テストは早かったのか?そこで役に立つのがサービスコンテナです。救世主サービスコンテナサービスコンテナとはサービスコンテナについてはドキュメントを見てみてください。Laravel他にもちょいちょい解説している記事を見かけるので、ggったりしてみてください。ちなみにJavaのDIコンテナと名前が違うだけで考え方は同じものです。使い方サービスコンテナを利用してこの問題を解決するには実装でサービスコンテナを利用している必要があります。サービスプロバイダーによってApp¥Models¥UserModelRepositoryに対して、UserModelクラスのインスタンスがサービスコンテナに登録されている状態だとしましょう。プロバイダー内のregisterメソッドを抜粋すると以下の様な感じです。App¥Models¥UserModelRepository;するとクロージャ内に書かれているようにUserModelのインスタンスが注入されるようになります。コントローラーで使用する方法は以下のようになります。}}テストでの解決策ここまでサービスコンテナの説明みたいになってしまいましたが、本題であるUserModelピンポイントでモック化する方法をお話します。}}何をしているのかというと、以下の様な手順でモック化を実現しています。テストメソッド内でサービスコンテナにApp¥Models¥UserModelRepositoryの名前で登録されている内容を上書きするテストメソッドによりアプリケーションへのアクセスが発生するコントローラーはApp¥Models¥UserModelRepositoryをUserModelとして呼び出すのでテストクラス内で生成したモッククラスを返す実行されるメソッドも当然モッククラスのメソッドというわけです。これにより簡単にアプリケーションテストでクラスのモック化を実現することができました!!!まとめ普通にアプリケーションを書くだけだとクラス間の結合がある程度、疎になる以外のメリットがなかなか見いだせないサービスコンテナでしたが、今回の出来事で僕はすっかりサービスコンテナ推進派になりました。いって乱用はよくないのできちんとどんなメリットがあるかを理解した上で使ってみるとテスト、保守しやすいアプリケーションに少しずつ近づけるのではないかなと思います。