PrincipalとUserServiceの利用のあるコントローラーのテスト
さて、JDOControllerTestCaseを使うと、
Controllerのテストが容易なのですが、
request.getPrincipalをした際に、
java.lang.UnsupportedOperationException
が発生する。
MockHttpServletRequestがそういうソースになっているわけで、
上記はエラーにならなくなりました。が、返す値がnullかどうか? で権限チェックをしていますので、その値をダミーにする必要がありますので その対応としても以下に続きます
じゃぁテストどうしようかなぁ・・・
と思って、該当ControllerのMoc(認証メソッドは適当な値を返す)に対してテストを行い、
というよくある単体テスト手法が出来るか?調べてみたが、MocのControllerを返す方法がなさそう・・・
もちろんそのMocに合わせたパスにすればいいんだろうけど、それだとちょっと違うしねぇ
リクエストスコープにControllerConstants.CONTROLLER_KEYで突っ込んでおけば、
そっちを利用してくれるという動作をしてくれればいいな〜と思ったけど、
そもそもControllerはちゃんとFrontControllerを通して取得されているので、
単体テストの為にそこを融通できないだろうしなぁ・・・と。
追記 Mocを利用したテスト
モックはやはりパスを変えて呼び出そうということで。
/xxx/hoge
に対するHogeControllerをモックを利用してテストをしたければ、
HogeMocControllerを作成し、
/xxx/hogeMoc
に対するテストを記述します。
また、ルールも決めておくと後々戸惑わないでしょう。
こんな感じ?
基本、コントローラにはMocという名前をつけないルールとし、
モックを利用したテスト時には、
mocのパスを指定してテストをし、敢えて「モックを利用している」と明示するというルールとする
なんだったら、一個/moc/のようにパスをきってしまったほうが潔いかもしれませんね。
(相対パス的にずれるようだとまずいけど)
注意点
ただし、インナークラスで作成したコントローラーはFrontControllerでインスタンス化できないので、
ちゃんとした(という表現は不適?)クラスとして作成する必要があります。
また、testのソースフォルダの出力先が、デフォルトとなっていると、Mocもデプロイされるので、
mocのパスも有効になってしまいます。
それを避けるためにも、testの出力先はデフォルトとは別にするのは忘れないように。
UserPrincipalのテストをしたい
Principalの値によるテストを行ないたいので、
Principalを返すテストの場合は以下のように設定
(nullを返す必要のあるテストの場合ではnullを返してやる)
request = new MockHttpServletRequest(application) { @Override public Principal getUserPrincipal() { return new Principal() { @Override public String getName() { return "moc for unit test"; }}; } };
UserServiceを利用する場合のテスト
UserServiceを利用している部分をテストする。
以下は管理者としてログイン済みにする
ApiProxy.setEnvironmentForCurrentThread(new ApiProxy.Environment(){ public String getAppId() { return "Unit Tests"; } public String getVersionId() { return "1.0"; } public void setDefaultNamespace(String s) { } public String getRequestNamespace() { return "gmail.com"; } public String getDefaultNamespace() { return ""; } public String getAuthDomain() { return "gmail.com"; } public boolean isLoggedIn() { //認証済み return true; } public String getEmail() { return ""; } public boolean isAdmin() { //管理者 return true; } });
全体
public void testRun() throws Exception { //管理者でログイン済みの設定 ApiProxy.setEnvironmentForCurrentThread(new ApiProxy.Environment(){ public String getAppId() { return "Unit Tests"; } public String getVersionId() { return "1.0"; } public void setDefaultNamespace(String s) { } public String getRequestNamespace() { return "gmail.com"; } public String getDefaultNamespace() { return ""; } public String getAuthDomain() { return "gmail.com"; } public boolean isLoggedIn() { //認証済み return true; } public String getEmail() { return ""; } public boolean isAdmin() { //管理者 return true; } }); //Principalを使うので request = new MockHttpServletRequest(application) { @Override public Principal getUserPrincipal() { return new Principal() { @Override public String getName() { return "moc for unit test"; }}; } }; //パラメータをセット param("result", "2000/10/12,2,01,09,16,20,21,43,05,0,0,7,13188800,195,568100,8426,11500,144860,1000,102580607,"); //リクエストを走らせる start("/post/insert"); InsertController controller = getController(); assertNotNull(controller); assertTrue(isRedirect()); assertEquals("/post/", getNextPath()); //refreshPersistenceManager(); int count = count(Result.class); assertEquals(1, count); Result result = pm.getObjectById(Result.class, KeyFactory.createKey(Result.class.getSimpleName(), "days_2000/10/12")); assertEquals("2000/10/12", result.getDate()); //その他各値のチェック }