Search code examples
scalaunit-testingscalatestplayframework-2.6

Playframework FakeRequest withFormUrlEncodedBody data is lost


What I want to do : I try to test a action method addbook with FakeRequest like below.

 val request = FakeRequest()
    .withSession("email" -> "admin@admin.co.jp", "name" -> "yun", "id" -> "1")
    .withFormUrlEncodedBody(
      "name" -> "Great Gatsby",
      "price" -> "30",
      "author" -> "Scott",
      "description" -> "Great classic"
    )
    .withCSRFToken

  val result = homeController.addBook(request).run()(materializer)
  flash(result).get("msg") mustBe Some("some msg")
  status(result) must equal(SEE_OTHER)
  redirectLocation(result) mustBe Some("/somelocation")

What is wrong : But the when I bindFromRequest the Form data, I get nothing but form constraint errors.

[warn] c.HomeController - data : 
[warn] c.HomeController - errors : FormError(name,List(error.required),List()), FormError(price,List(error.required),List())

addBookForm is defined with at least two fields ("name", "price") that are required

val addBookForm = Form(
mapping(
  "name" -> nonEmptyText,
  "price" -> longNumber,
  "author" -> optional(text),
  "description" -> optional(text),
  "pictures" -> Forms.list(text).verifying("more than 5 pictures detected", list => list.size <= 5),
  "reserved" -> optional(boolean),
  "publisher" -> optional(longNumber),
)(BookFormData.apply)(BookFormData.unapply)
)

The addbook action definition is like below.

def addBook = isAuthenticatedAsync { (userId, userName, userEmail) =>
implicit request =>

  logger.warn("data : " + addBookForm.bindFromRequest.data.mkString(", "))
  logger.warn("errors : " + addBookForm.bindFromRequest.errors.mkString(", "))
  ....

And isAuthenticatedAsync

def isAuthenticatedAsync (f: => (String, String, String) => MessagesRequest[AnyContent] => Future[Result]) = Security.Authenticated(userInfo, onUnauthorized) { user =>
    Action.async(request => f(user._1,user._2,user._3)(request))
  }

When I change isAuthenticatedAsync to just Async method, I can get the form data but I don't know what I'm missing, why it is not working.

Please tell me what I'm missing?

Have a great day!

EDIT

I've included that addbookForm code.

Just to emphasize, the addbook action works as expected with real request(via browser) But when I test it with Faketest, the form data is lost


Solution

  • I got the answer from schmitch(Schmitt Christian).

    He responded to my question that I also posted to discuss list of lightbend.

    https://discuss.lightbend.com/t/fakerequest-withformurlencodedbody-data-is-lost/636/3

    So the bottom line is instead of using run() method, use the method :

    def call[T](action: EssentialAction, req: Request[T])(implicit w: Writeable[T], mat: Materializer): Future[Result] = call(action, req, req.body)

    The further explanation is described in the original answer in the link above.