如何在功能测试中获得CSRF令牌?它无法在会话中保存令牌并在URL中提交。
"The `send` action" should {
"return status code 400 if subject is invalid" in new WithApp with Context {
val token = CSRF.Token(42.toString)
val Some(result) = route(FakeRequest(POST, helper.CSRF(routes.ContactUs.send())(token).toString())
.withFormUrlEncodedBody(
("subject" -> "invalid"),
("name" -> "Lucky Luke"),
("email" -> "test@test.com"),
("message" -> "test")
)
.withSession(TOKEN_NAME -> token.toString)
)
status(result) must equalTo(BAD_REQUEST)
contentType(result) must beSome("application/json")
charset(result) must beSome("utf-8")
}
修改
token.toString
不会将标记返回为字符串。访问者token.value
返回一个可以在会话中发送的正确令牌。一个有效的例子是:
"The `send` action" should {
"return status code 400 if subject is invalid" in new WithApp with Context {
val token = CSRF.Token(42.toString)
val Some(result) = route(FakeRequest(POST, helper.CSRF(routes.ContactUs.send())(token).toString())
.withFormUrlEncodedBody(
("subject" -> "invalid"),
("name" -> "Lucky Luke"),
("email" -> "test@test.com"),
("message" -> "test")
)
.withSession(TOKEN_NAME -> token.value)
)
status(result) must equalTo(BAD_REQUEST)
contentType(result) must beSome("application/json")
charset(result) must beSome("utf-8")
}
答案 0 :(得分:1)
您的解决方案有效,但为了不对每个请求执行此操作并进行更清晰的测试,您可以使用自定义GlobalSettings
。这样做有两件事:删除csrf检查过滤器但仍在会话中提供csrf令牌,因此csrf帮助程序不会阻塞。
object TestGlobal extends WithFilters(FakeCSRF)
object FakeCSRF extends Filter{
def apply(next: (RequestHeader) => Result)(request: RequestHeader) = {
next(CSRF.addRequestToken(request,CSRF.generate))
}
}
然后为测试定义自定义范围:
trait testApp extends Scope with Around{
def around[T](t: => T)(implicit evidence$1: AsResult[T]) = {
Helpers.running(FakeApplication(withGlobal = Some(TestGlobal)))(AsResult(t))
}
}
现在,在你的测试中,你可以做到:
"The `send` action" should {
"return status code 400 if subject is invalid" in new testApp {
val Some(result) = route(FakeRequest(POST, routes.ContactUs.send())
.withFormUrlEncodedBody(...)
}
}
请注意,测试代码中没有提及CSRF。
警告:如果您没有路由您的虚假请求,而是直接调用控制器,则此功能无效。不会使用TestGlobal,因此您需要使用更详细的解决方案。