scala - 使用依赖注入(inject)测试带有 SecureSocial 的 Play2 应用程序

标签 scala testing guice playframework-2.1 securesocial

非常感谢任何指导!

当我从浏览器运行 SecureSocial 插件时它工作正常,但我希望现在能够测试我的 Play 应用程序的其余部分。

快速介绍

SecureSocial 的语法如下所示:

def page = SecuredAction(WithProvider("google")) { ... }

或者这个:

def page = UserAwareAction { ... }

我一直在寻找here ,这似乎是 Stack Overflow 上唯一的问题,甚至与我使用 SecureSocial 的问题有很大关系,但我不太喜欢重新连接字节码。应该有一个更简单的解决方案。

当我运行访问受 SecureSocial 保护的操作的测试时,我收到一个很大的错误,我猜这基本上意味着我没有将它传递给用户。 (见本题底部)

我想做什么

注入(inject)所有函数以返回类型 Action 而不是 SecuredAction 或仅在测试期间返回 UserAwareAction

或者实际上将测试用户传递给调用。 但是如何呢?

我有什么

@Singleton
class JsonOps @Inject() () extends Controller with SecureSocial {...}

Global.scala 描述的写法here在我的测试中...

val controller = new JsonOps
val result = controller.userAwareActionRequestForSomeJson("")(FakeRequest())

我也有这样的电话:

// This is what I would use for production
def extjs = SecuredAction(WithProvider("google")) { implicit request =>
   Ok(views.html.extjs(request.user.firstName))
}
// This is what I would use for testing
def extjs = Action { implicit request =>
  Ok(views.html.extjs("testtesttesting"))
}

这就是为什么我认为这个问题可能非常适合依赖注入(inject)?我不确定如何进行类实例化,因为我使用的 Global.scala 是一个通用类实例化器。我也不特别希望为我拥有的每个 Controller 编写 9000 多个特征。

大错误

这是 UserOpsSpec.scala 的第 12 和 13 行:

12  val controller = new UserOps
13  val result = controller.extjs()(FakeRequest())

这是错误

[error]     RuntimeException: java.lang.ExceptionInInitializerError (UserOpsSpec.scala:13)
[error] play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:220)
[error] securesocial.core.SecureSocial$.authenticatorFromRequest(SecureSocial.scala:200)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:81)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:78)
[error] play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:215)
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:51)
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:51)
[error] play.api.Play$.current(Play.scala:51)
[error] securesocial.core.Authenticator$.cookieName$lzycompute(Authenticator.scala:188)
[error] securesocial.core.Authenticator$.cookieName(Authenticator.scala:188)
[error] securesocial.core.Authenticator$.<init>(Authenticator.scala:201)
[error] securesocial.core.Authenticator$.<clinit>(Authenticator.scala)
[error] securesocial.core.SecureSocial$.authenticatorFromRequest(SecureSocial.scala:200)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:81)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:78)
[error] play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:215)
[error] null
[error] securesocial.core.SecureSocial$.authenticatorFromRequest(SecureSocial.scala:200)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:81)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:78)
[error] play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:215)
[error] There is no started application
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:51)
[error] play.api.Play$$anonfun$current$1.apply(Play.scala:51)
[error] play.api.Play$.current(Play.scala:51)
[error] securesocial.core.Authenticator$.cookieName$lzycompute(Authenticator.scala:188)
[error] securesocial.core.Authenticator$.cookieName(Authenticator.scala:188)
[error] securesocial.core.Authenticator$.<init>(Authenticator.scala:201)
[error] securesocial.core.Authenticator$.<clinit>(Authenticator.scala)
[error] securesocial.core.SecureSocial$.authenticatorFromRequest(SecureSocial.scala:200)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:81)
[error] securesocial.core.SecureSocial$$anonfun$SecuredAction$1.apply(SecureSocial.scala:78)
[error] play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:215)
[info]

最佳答案

这是我解决这个问题的方法。我通过直接添加到内存中的 Authenticator 来模拟登录(某种)。这会返回一个我包含在虚假请求中的 cookie。我正在通过一些语法糖的隐式转换来做到这一点。您可以针对您的特定情况轻松扩展它。我的应用程序仅使用用户/密码提供程序,但您应该能够扩展以使用其他插件。

 object TestUtils {

  @inline implicit def loggedInFakeRequestWrapper[T](x: FakeRequest[T]) = new LoggedInFakeRequest(x)

  final class LoggedInFakeRequest[T](val self: FakeRequest[T]) extends AnyVal {
    def withLoggedInUser(id: Long) = {
      val userToLogInAs:Identity = ??? //get this from your database using whatever you have in Global
      val cookie = Authenticator.create(userToLogInAs) match {
        case Right(authenticator) => authenticator.toCookie
      }
      self.withCookies(cookie)
    }
  }        
}

和规范:

"render the index page" in {
      val home = route(FakeRequest(GET, "/").withLoggedInUser(1L)).get

      status(home) must equalTo(OK)
      //etc.
    }

关于scala - 使用依赖注入(inject)测试带有 SecureSocial 的 Play2 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17735636/

相关文章:

scala - elastic4s地理距离排序查询语法

scala - OpenJDK java.sql.Timestamp 与 Sun Java VM 的时间戳类不同吗?

java - Selenium Chrome 驱动程序选择证书弹出确认不起作用

java - Guice 注入(inject) servlet

regex - Scala,正则表达式匹配忽略不必要的单词

java - 字节数组到某种 Java/Scala 图像。性能考虑

node.js - 使用自定义错误处理程序时,是否可以使用 Mocha 测试 ExpressJS 中的错误处理?

testing - QTP、QC、Load Runner 和 RFT 教程

java - Guice 如何将 ServletContext/ServletConfig 传递给绑定(bind)?

java - Kotlin:向 guice 注入(inject)的依赖项添加一个接口(interface),以便我们可以仅出于单元测试目的而模拟它们?