2012-04-01 7 views
5

Ich spiele mit Play 2.0, Scala-Version. Zur Zeit analysiere ich Zentasks sample app.So testen Sie Zentasks Beispiel-App von Play 2.0

Einer der Teil dieser App ist Authentifizierungsmechanismus meist in Secured Merkmal abgedeckt. Ich frage mich, wie ich gesicherte Aktionen testen kann, z. index von Projects controller.

Für nicht-gesicherte Aktion, würde ich wahrscheinlich so etwas wie

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

tun, um eine Aktion auszuführen und das Ergebnis zu bekommen.

Was soll ich im Falle einer gesicherten Aktion tun?

Disclaimer: Ich bin total neu in Scala und Play, also sind alle Hinweise sehr wertvoll. Vielen Dank!

Antwort

1

ok, ich bin auch kein großer Experte, aber hier ist eine Idee.

Erstellen Sie eine trait InSecure trait extends Secured, die die gesicherten Aktionen überschreibt und immer Zugriff erlaubt. Dann können Sie eine object InSecureProjects extends Projects with InSecture in Ihrem Test machen, dies sollte nur die Sicherheitsprüfungen überschreiben und lassen Sie die Aktionen ohne jede Sicherheit testen.

Jetzt, anstatt die Tests auf Projects auszuführen, führen Sie sie auf InSecureProjects. Sie können das gleiche für die anderen gesicherten Controller tun.

ich es nicht getestet haben, so lassen Sie mich wissen, ob es funktioniert;)

2

Es gibt eine fix for the integrated approach to this in Playframewrk v2.1 habe ich eine backport of the fix on the 2.0.x branch

Bis es verschmolzen wird und freigegeben wird, ist hier Was ich getan habe (es funktioniert auf Play 2.0.3+):

Ich habe mein eigenes Helpers-Objekt in einem libs-Paket wie folgt definiert.

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)) 
    } 
    } 

} 

Dann in meinem Test importiere ich meine Helfer und den ganzen Stück Helfer Kontext, mit Ausnahme von routeAndCall:

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

ich dann verwenden, um eine Around Setup meine app (Ich brauche die eine Anwendung zur Verfügung stellen. Geheimnis, wie ich speichern die Benutzer authentifiziert Namen in der Sitzung, die auf einem unterzeichneten Cookie)

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 
     } 
    } 
    } 

Dies ermöglicht es mir, basiert die folgenden Tests zu schreiben:

"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") 
    } 

Es ermöglicht Ihnen, den gesicherten Code auszuüben, obwohl es kein Komponententest ist.