如何测试扩展ActionBuilder的自定义Action?

时间:2015-01-22 22:36:53

标签: scala playframework

我想编写一个单元测试来测试我的自定义操作构建器。

一旦我在我的测试中将ActionWithSession设置为实例,我如何实例化它就像在控制器中一样?

如果重定向或返回会话,我如何测试边缘情况?

class SessionAwareRequest[A](val context: MyContext, request: Request[A]) extends WrappedRequest[A](request)

class ActionWithSession @Inject()(siteConfig: SiteConfig, userService: UserService)
  extends ActionBuilder[SessionAwareRequest] {

  def invokeBlock[A](request: Request[A], block: (SessionAwareRequest[A]) => Future[Result]) = {
    val session = loadSession(request)

    if(session.isDefined) {
      val result: Future[Result] = block(new SessionAwareRequest(session.get, request))
      result.map(_.withCookies(CookieHelper.newSession(session.get)(request)))
    }
    else {
      Future.successful(Results.Redirect(routes.MessagesController.show("error!"))) 

  }

  def loadSession(requestHeader: RequestHeader): Option[MySession] = {
    ...
      Some(MySession(...))
    else
      None
  }

}

1 个答案:

答案 0 :(得分:3)

如果你正在使用Play 2.3,你应该能够利用PlaySpecification特征,它提供call方法来测试动作。看一下Documentation,特别是关于"单元测试EssentialAction的部分 "

这是一个基于您发布的代码的人为的最小示例。它基本上只是检查请求头是否包含" foo"字段,如果是这样,返回OK以及另外一个cookie" baz"通过自定义操作构建器添加的。如果" foo"标头丢失,返回BadRequest。希望它有所帮助。

import play.api.mvc._
import play.api.test.{FakeRequest, PlaySpecification}
import scala.concurrent.Future

class ActionSpec extends PlaySpecification {
  case class MySession()

  class SessionAwareRequest[A](val context: MySession, request: Request[A]) extends WrappedRequest[A](request)

  object ActionWithSession extends ActionBuilder[SessionAwareRequest] {

    def loadSession(requestHeader: RequestHeader): Option[MySession] = {
      if (requestHeader.headers.get("foo").isDefined)
        Some(MySession())
      else
        None
    }

    def invokeBlock[A](request: Request[A], block: (SessionAwareRequest[A]) => Future[Result]): Future[Result] = {
      val session = loadSession(request)

      if (session.isDefined) {
        val result: Future[Result] = block(new SessionAwareRequest(session.get, request))
        result.map(_.withCookies(Cookie("baz", "quux")))
      } else {
        Future.successful(Results.BadRequest)
      }
    }
  }

  "My custom action" should {

    "return HTTP code 400 in case the request header does not contain a 'foo' field" in {
      val foo = call(ActionWithSession { request =>
        Results.Ok("Yikes")
      }, FakeRequest())
      status(of = foo) must beEqualTo(BAD_REQUEST)
      cookies(of = foo).get("baz") must beNone
    }

    "return HTTP code 200 in case the request header does contain a 'foo' field" in {
      val foo = call(ActionWithSession { request =>
        Results.Ok("Yikes")
      }, FakeRequest().withHeaders("foo" -> "bar"))
      status(of = foo) must beEqualTo(OK)
      cookies(of = foo).get("baz") must beSome
    }
  }

}