11

I'm stuck on a little problem with my functionnal testing.

I have a Play! 2.5 scala project in which I added CSRF verification on some forms, the associated scala-test units test failed, as expected, with the error :

java.lang.RuntimeException: No CSRF token present!

I'm using FakeRequest with routes in order to test them :

val fakeRequest   = FakeRequest(GET, s"/backOffice/login")
val Some(result)  = route(app, fakeRequest)

How could I add the CRSF Token in order to render my test successful again ?

(Thank you, and sorry for bad english, I'm not native)

3
  • 1
    You could override you application.conf and set some headers for bypassing CSRF, like here. Or look at this answer. Commented Oct 26, 2016 at 7:10
  • Hi, thanks for answering me ! I should have precised that I'm also testing templates, and that I'm doing CSRF protection on a per action basis (The second case in the documentation, not the first one with a filter). Due to this, I can't just bypass CSRF as my template need a CSRF token to be present in the FakeRequest, like in second link, which I had already tested (should have precised that too, sorry), but it's for play 2.2.1, and Intellij is yelling at me "Cannot resolve symbol SignedTokenProvider" Have you an idea how I could do that in play 2.5 ? Commented Oct 26, 2016 at 8:33
  • 1
    Found a solution and made a trait :) look to the answer I added if you're interested ^^ Commented Oct 26, 2016 at 10:16

1 Answer 1

11

Update : Like haui said in his comment :

Seems like they added something similar in play version 2.6. There you can use import play.api.test.CSRFTokenHelper._ FakeRequest().withCSRFToken (Scala) and CSRFTokenHelper.addCSRFToken(requestBuilder) (Java) as explained in the Migration guide

For people who are still in 2.5.6, my answer still apply :

So, after looking in Play-scala classes for a certain time, I finally found a way to adapt this answer : https://stackoverflow.com/a/19849420/4496364 to Play 2.5.6

I even made a trait, so if someone need it one day, here it is :

import play.api.Application
import play.api.test.FakeRequest
import play.filters.csrf.CSRF.Token
import play.filters.csrf.{CSRFConfigProvider, CSRFFilter}

import scala.language.postfixOps

trait CSRFTest {
  def addToken[T](fakeRequest: FakeRequest[T])(implicit app: Application) = {
    val csrfConfig     = app.injector.instanceOf[CSRFConfigProvider].get
    val csrfFilter     = app.injector.instanceOf[CSRFFilter]
    val token          = csrfFilter.tokenProvider.generateToken

    fakeRequest.copyFakeRequest(tags = fakeRequest.tags ++ Map(
      Token.NameRequestTag  -> csrfConfig.tokenName,
      Token.RequestTag      -> token
    )).withHeaders((csrfConfig.headerName, token))
  }
}

To use it, simply extend your test class with it, like this :

class LoginSpec extends PlaySpec with OneAppPerSuite /* or whatever OneApp */ with CSRFTest

then, instead of calling

val fakeRequest = FakeRequest(/* params */)

simply call

val fakeRequest = addToken(FakeRequest(/* params */))

I tried to make it look like the addToken{} in the Controller :)

Sign up to request clarification or add additional context in comments.

1 Comment

Seems like they added something similar in play version 2.6. There you can use FakeRequest().withCSRFToken (Scala) and CSRFTokenHelper.addCSRFToken(requestBuilder) (Java) as explained in the Migration guide

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.