Как протестировать пример приложения Zentasks из Play 2.0 - PullRequest
5 голосов
/ 01 апреля 2012

Я играю с Play 2.0, версия Scala. В настоящее время я анализирую пример приложения Zentasks .

Одной из частей этого приложения является механизм аутентификации, в основном охваченный чертой Secured. Мне интересно, как я могу проверить защищенные действия, напр. index из Контроллер проектов .

Для небезопасных действий я бы, вероятно, сделал что-то вроде

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

для запуска действия и получения его результата.

Что мне делать в случае защищенного действия?

Отказ от ответственности : Я абсолютно новичок в Scala и Play, поэтому все советы очень полезны. Спасибо!

Ответы [ 2 ]

2 голосов
/ 23 октября 2012

Существует исправление для интегрированного подхода к этому в Playframewrk v2.1. У меня есть бэкпорт исправления в ветке 2.0.x

Доон объединяется и выпускается, вот что я сделал (это работает в Play 2.0.3+):

Я определил свой собственный объект Helpers в пакете 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 => _,_}

Затем я использую Around для настройки моего приложения (мне нужнопредоставить application.secret, поскольку я сохраняю аутентифицированное имя пользователя в сеансе, основанном на подписанном файле 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", "foobar@example.com", "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", "foobar@example.com"))
      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")
    }

Он позволяет вам использовать защищенный код, даже если он не является модульным тестом.

1 голос
/ 02 сентября 2012

Хорошо, я тоже не большой специалист, но вот идея.

Создайте trait InSecure trait extends Secured, который отменяет защищенные действия и всегда разрешает доступ. Затем вы можете сделать object InSecureProjects extends Projects with InSecture в своем тесте, это должно переопределить только проверки безопасности и позволить вам тестировать действия без какой-либо защиты.

Теперь вместо запуска тестов на Projects вы запускаете их на InSecureProjects. Вы можете сделать то же самое для других защищенных контроллеров.

Я не проверял это, поэтому дайте мне знать, если это работает;)

...