本文介绍了使用依赖项注入通过SecureSocial测试Play2应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

非常感谢您的指导!

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

The SecureSocial plugin works fine when I run it from the browser, but I would like to be able to test the rest of my Play app now.

SecureSocial的语法如下:

SecureSocial's syntax looks like this:

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

或者这个:

def page = UserAwareAction { ... }

我一直在此处关于堆栈溢出的唯一问题甚至与我与SecureSocial的问题远程相关,但是我不太喜欢重新连接字节码.应该有一个更简单的解决方案.

I've been looking here, which seems to be the only question on Stack Overflow even remotely related to my problem with SecureSocial, but I don't quite fancy rewiring bytecode. There should be a simpler solution to this.

在运行访问受SecureSocial保护的操作的测试时,我收到一个大错误,我认为基本上是我没有将其传递给用户. (请参阅此问题的底部)

When I'm running tests that access SecureSocial-protected Actions, I get a large error that I guess basically means I'm not passing it a user. (see the bottom of this question)

要么注入所有函数以仅在测试期间返回类型Action而不是SecuredActionUserAwareAction

Either inject all the functions to return a type Action instead of SecuredAction or UserAwareAction only during testing

或实际上将测试用户传递给该呼叫. 但是如何?

Or actually pass in a test user to the call. But how?

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

按照此处和中所述编写的Global.scala我的测试...

A Global.scala written as described here and in my test...

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

为什么我认为此问题可能非常适合依赖项注入?我不确定如何执行类实例化,因为我正在使用的Global.scala是一个通用的类实例化器.我也不希望为我拥有的每个控制器写9000+个特征.

Which is why I think this problem might be well-suited for dependency injection? I'm not sure how I would do the class instantiation though, since the Global.scala I'm using is a generic class instantiator. I don't particularly wish to write 9000+ traits for each controller I have either.

这是UserOpsSpec.scala第12和13行:

This is line UserOpsSpec.scala line 12 and 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]

推荐答案

这是我解决此问题的方法.我通过直接添加到内存中的身份验证器来模拟登录(某种).这将返回一个包含在虚假请求中的cookie.我通过对某些语法糖进行隐式转换来实现此目的.您可以针对特定情况轻松扩展它.我的应用程序仅使用user/pass提供程序,但您应该可以扩展以使用其他插件.

Here's how I solved this problem. I am simulating a login (kind of) by directly adding to the Authenticator that's in memory. That returns a cookie which I include in the fake request. I'm doing this with an implicit conversion for some syntactic sugar. You can easily extend it for your particular case. My application only uses the user/pass provider, but you should be able to extend to use the other plugins.

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

这篇关于使用依赖项注入通过SecureSocial测试Play2应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 14:59