非常感谢任何指导!
当我从浏览器运行SecureSocial插件时,它运行正常,但我希望能够立即测试我的Play应用程序的其余部分。
SecureSocial的语法如下所示:
def page = SecuredAction(WithProvider("google")) { ... }
或者这个:
def page = UserAwareAction { ... }
我一直在寻找here,这似乎是Stack Overflow上唯一与SecureSocial的问题远程相关的问题,但我不太喜欢重新编码字节码。应该有一个更简单的解决方案。
当我运行访问受SecureSocial保护的操作的测试时,我得到一个大错误,我猜这基本上意味着我没有将它传递给用户。 (见本问题的底部)
注入所有函数以仅在测试期间返回类型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"))
}
这就是为什么我认为这个问题可能非常适合依赖注入?我不确定如何进行类实例化,因为我正在使用的Global.scala是一个泛型类实例化器。我并不特别希望为每个控制器编写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]
答案 0 :(得分:2)
以下是我解决这个问题的方法。我通过直接添加到内存中的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.
}