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());
        //その他各値のチェック
    }