2012/01/07(土)Slim3でモックテストを実施する
Slim3のアプリのテスト時に、Serviceにモックを差し込んで、Controllerのみのテストを行いたいケースがあると思います。DIコンテナを使っていれば、Serviceに注入するImplをモックにすればいいと思いますが、GAEでDIを使うのはちょっと現実的ではありません。というわけで、テスト時にDIコンテナっぽく振る舞うUtilクラスを作ってみました。
https://github.com/7pairs/Slim3Utils/blob/master/src/jp/gr/java_conf/ruquia/utils/MockUtil.java
人様に見せるんだったら、パッケージ名を取得するときにruquiaなんて名前で登録するんじゃなかったなw
さて、実際の使い方です。まず、テストしたいControllerを継承したクラスを作り、そのコンストラクタでこのUtilを使用します。以下のサンプルは、テスト対象のTestControllerにserviceというTestServiceのprivateフィールドがいること、TestServiceにはfooMethod、barMethodがいることを前提にしています。
public class TestWithMockController extends TestController { public TestWithMockController(){ super(); try{ MockUtil.inject( this, "service", new TestService() { @Override public String fooMethod() { return null; } @Override public List<String> barMethod(String arg) { return null; } } ); } catch(Exception e) { e.printStackTrace(); } } }
これでモックを差し込んだControllerができました。なお、サンプルは差し込むモックを匿名クラスにしましたが、もちろんきちんとしたクラスを作っても構いません。
さて、今度はテストプログラムのソースを修正します。Controllerのテストプログラムにtester.startメソッドを呼んでいる箇所があると思います。
tester.start("/test");
この部分を、先ほど作ったTestWithMockControllerを呼ぶように修正します。例えば、TestControllerと同じパッケージにTestWithMockControllerを作った場合、以下のように書き換えます。
tester.start("/testWithMock");
あとはテストを実行するだけです。
ちなみに、私はテストのためだけにアクセス範囲を変えるのが嫌だったのでここまでやりましたが、ぶっちゃけここまで苦労するくらいなら、最初からserviceフィールドをprotectedにして、テストプログラムから直接serviceを制御するほうがはるかに楽だったりします。このあたりは好みの問題だと思いますが。