2012年2月29日水曜日

Slim3 Source Code Reading #10

今日はSlim3 Source Code Reading #10でした。

前回に引き続き、testerを読み進めました。
今日は、以下のファイルを読みました。

  • ControllerTestCase.java
  • ControllerTester.java
  • ServletTester.java

ControllerTestCase.javaはAppEngineTestCaseと同じように中身は
testerというメンバ変数があるだけでした。ので、スルー。

testerはControllerTesterクラスの変数なので、そのまま、ControllerTester.javaに
進みました。

ControllerTesterはsetUpで、初期化パラメータの読み込みと、
FrontControllerの初期化を行っています。
これが、リクエストを受け取った時のFilterの初期化の代わりとなっているようです。

tearDownは後処理が行われて終わりです。

startメソッドが、実際にControllerを実行するメソッドですが、内部でRouterも
読み取るので、Routerの設定は反映されます。

以下の3メソッドはControllerに合わせてあるのだと思いますが、
中身も少ないので、概要だけ。
getDestinationPathは遷移先のパスを返します。
getControllerはrequestScopeに格納されているControllerを返します。
getErrorsはValidationエラーの情報を取得します。

最後にServletTester.javaですが、
setUpでは、元の設定を退避し、本番環境に合わせるように設定されるようです。
例えば、タイムゾーンは"UTC"をセットしていますし、ロケールはLocale.USがセットされます。

tearDownで、退避していた元の設定を復元しています。

param()はパラメータの取得/設定します。このメソッドを使ってテスト前の
パラメータを指定する事ができます。
paramValues()はパラメータを配列で取得/配列を設定します。

以下のメソッドは型変換を行った後の値を返すメソッドです。
Controllerクラスにもありました。パラメータの型もチェックしたい場合は
利用した方が良いでしょう。
asShort()
asInteger()
asLong()
asFloat()
asDouble()
asString()
asBoolean()
asDate()
asKey()

以下のメソッドは、それぞれのスコープの値を取得/設定します。
requestScope()
sessionScope()
applicationScope()

isRedirect()はリダイレクト先のパスが設定されていればTrueを返します。

今日は、薄い内容で終わるかと思ったのですが、最後の

addBlobKey()でハマりました。
これは、Blobstoreのテストを行うために、実行前にBlobstoreのKeyを設定
しておくものだと思うのですが、どうしても使い方がわからなかったので
slim3Demoのソースコードを見ました。

使い方としては、第1引数にブラウザからのパラメータ名を指定し、
第2引数には恐らく、BlobKeyの文字列を渡すのだと思っているのですが、
どうしてもテストがうまくいかない。
JUnitのトレースを見ると、以下のような表示になりました。
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List
at com.google.appengine.api.blobstore.BlobstoreServiceImpl.getUploads(BlobstoreServiceImpl.java:162)
at com.google.appengine.api.blobstore.BlobstoreServiceImpl.getUploadedBlobs(BlobstoreServiceImpl.java:135)
at slim3.demo.controller.blobstore.UploadController.run(UploadController.java:21)
at org.slim3.controller.Controller.runBare(Controller.java:111)
at org.slim3.controller.FrontController.processController(FrontController.java:491)
at org.slim3.controller.FrontController.doFilter(FrontController.java:277)
at org.slim3.controller.FrontController.doFilter(FrontController.java:237)
at org.slim3.controller.FrontController.doFilter(FrontController.java:199)
at org.slim3.tester.ControllerTester.start(ControllerTester.java:131)
at slim3.demo.controller.blobstore.UploadControllerTest.run(UploadControllerTest.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
どうやら、キャストで失敗しているようで、バグなのでは?という結論で、
読書会としてはタイムアップ。

その後、Twitterで、「slim3DemoがSDK1.6.0だと動作した」という報告が
あったので、私も同様にslim3Demoをダウンロードした後、実行してみると
同じ例外で失敗する結果となりました。

私の環境はSDK1.6.2.1なので、何か変わったのかと思ってSDKのソースをみると、
確かに変わっていました。

以下のリンクは、SDKのソースコードのDiffです。

元々は、Map<String, String>で扱っていたようなのですが、
Map<String, List<String>>に変わってしまったようで、
最新のSDKだとaddBlobKeyを使っても
テストは動作しないという結果になってしまいました。

現時点では、Slim3の更新を待つか、
requestScopeに以下のKeyで型をあわせてセットすれば動くかもしれません。
com.google.appengine.api.blobstore.upload.blobkeys

という事で、次回もtester(MockXXX)から読み進めます。

次回は3/6(火) 19:00〜を予定しています。ご興味がありましたらどうぞ。