2012-04-01 5 views
5

Play 2.0、Scala版で遊んでいます。現在、私はZentasks sample appを分析しています。Play 2.0からZentasksサンプルアプリをテストするには

このアプリケーションの一部の1つは、ほとんどがSecuredの特性でカバーされている認証メカニズムです。私はどのように安全な行動をテストすることができるのだろうか? indexからProjects controllerまでである。・固定されていないアクションの

、私はおそらく、アクションを実行し、その結果を得るために

val result = controllers.Projects.index(FakeRequest()) 

ような何かをしたいです。

保護された処置の場合はどうすればよいですか?

免責事項:私はScalaとPlayの両方に全く新しいので、すべてのヒントは非常に貴重です。ありがとう!

答えて

1

私は偉大な専門家でもありませんが、ここにはアイデアがあります。

セキュリティで保護された操作を上書きし、常にアクセスを許可するtrait InSecure trait extends Securedを作成します。 次に、テストでobject InSecureProjects extends Projects with InSectureを作成することができます。これはセキュリティチェックだけをオーバーライドし、セキュリティなしでアクションをテストできるようにする必要があります。

Projectsでテストを実行する代わりに、InSecureProjectsでテストを実行します。他のセキュリティで保護されたコントローラでも同じことができます。

私はそれをテストし、それが動作するかどうか私に知らせていない;)

2

私はbackport of the fix on the 2.0.x branch

それが合併してリリースされるまでは、ここにあるを持ってPlayframewrk v2.1の中fix for the integrated approach to thisがあります私は何をしましたか(Play 2.0.3以降で動作します):

私は自分のヘルパーオブジェクトをlibsパッケージのように定義しました。

package libs 

import play.api.mvc._ 

import play.api.libs.iteratee._ 
import play.api.libs.concurrent._ 
import play.api.test._ 

object Helpers { 

    def routeAndCall[T](request: FakeRequest[T]): Option[Result] = { 
    routeAndCall(this.getClass.getClassLoader.loadClass("Routes").asInstanceOf[Class[play.core.Router.Routes]], request) 
    } 
    /** 
    * Use the Router to determine the Action to call for this request and executes it. 
    */ 
    def routeAndCall[T, ROUTER <: play.core.Router.Routes](router: Class[ROUTER], request: FakeRequest[T]): Option[play.api.mvc.Result] = { 
    val routes = router.getClassLoader.loadClass(router.getName + "$").getDeclaredField("MODULE$").get(null).asInstanceOf[play.core.Router.Routes] 
    routes.routes.lift(request).map { 
     case a: Action[_] => 
     val action = a.asInstanceOf[Action[T]] 
     val parsedBody: Option[Either[play.api.mvc.Result, T]] = action.parser(request).fold(
      (a, in) => Promise.pure(Some(a)), 
      k => Promise.pure(None), 
      (msg, in) => Promise.pure(None) 
     ).await.get 

     parsedBody.map{resultOrT => 
      resultOrT.right.toOption.map{innerBody => 
      action(FakeRequest(request.method, request.uri, request.headers, innerBody)) 
      }.getOrElse(resultOrT.left.get) 
     }.getOrElse(action(request)) 
    } 
    } 

} 

はその後、私のテストで私はrouteAndCallを除いて、私のヘルパーと全体のプレイヘルパーコンテキストをインポート:

import libs.Helpers._ 
import play.api.test.Helpers.{routeAndCall => _,_} 

私は、周りのセットアップに私のアプリを使用する(私はアプリケーションを提供する必要があります。

:これは私には、次のテストを書くことができます

def appWithSecret():Map[String,String]={ 
    Map(("application.secret","the answer is 42 !")) 
    } 


    object emptyApp extends Around { 
    def around[T <% Result](t: => T) = { 
     running(FakeApplication(additionalConfiguration = inMemoryMongoDatabase("emptyApp")++appWithSecret())) { 
     User(new ObjectId, "Jane Doe", "[email protected]", "id1").save() 
     t // execute t inside a http session 
     } 
    } 
    } 

)私が署名したクッキーに基づいてセッションに認証されたユーザー名を保存するように秘密
"respond to the index Action" in emptyApp { 
     val request: FakeRequest[AnyContent] = FakeRequest(GET, "/expenses").withSession(("email", "[email protected]")) 
     val Some(result) = routeAndCall(request) 

     status(result) must equalTo(OK) 
     contentType(result) must beSome("application/json") 
     charset(result) must beSome("utf-8") 
     contentAsString(result) must contain("Hello Bob") 
    } 

単位テストではないにもかかわらず、セキュリティ保護されたコードを実行することができます。

関連する問題