2013-04-29 51 views
2

如何在功能測試中獲得CSRF令牌?它無法在會話中保存令牌並將其提交到URL中。如何在功能測試中獲得CSRF令牌

"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" -> "[email protected]"), 
     ("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" -> "[email protected]"), 
     ("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") 
} 

回答

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不會被使用,因此您需要使用更詳細的解決方案。