Controller action returns "Invalid Json" when using a Fakerequest from a spec2 test

431 views Asked by At

I am using playframework 2.6 and play-slick 0.8.0.

Action code:

def addCompany = Authenticated {
 DBAction(parse.json) {
   implicit rs => {
     val newCompany = rs.request.body
     val result = CompanyTable.insert(newCompany.as[Company])(rs.dbSession)

     if(result > 0)
       Ok("{\"id\":"+result+"}")
     else
       Ok("New company was not created.")
   }
 }
}

The Action is a composition of an Action that just checks for a valid session and the DBAction, which requires the request body to have a valid JSON object.

Test code:

"should create a Company from a Json request" in new InMemoryDB {

  val newCompany = Company(name = "New Company1")

  val fr = FakeRequest(POST, "/company")
    .withSession(("email", "[email protected]"))
    .withHeaders(CONTENT_TYPE -> "application/json")
    .withJsonBody(Json.toJson(newCompany))

  val action = controllers.CompanyController.addCompany

  val result = action(fr).run

  status(result) should be_==(OK)
  (contentAsJson(result) \ "id").as[Long] should be_>(1L)

}

The InMemoryDB class is just a FakeApplication with a pre-populated in memory database.

The issue that I am having is that when the test runs the result is always a 400 with body content containing a message saying [Invalid Json]. When I call the service using curl with the same JSON body content, it works and the id is returned.

1

There are 1 answers

0
eeb On BEST ANSWER

I decided to build a separate test project, and I used the activator to create a seed for the new project. I noticed that in the generated test that a different method of calling the action was used, so I switched my project to use this method. It worked, but I don't know why.

New code:

"should create a Company from a Json request" in new InMemoryDB {

  val newCompany = Company(name = "New Company1")

  val action = route(
    FakeRequest(POST, "/company")
      .withSession(("email", "[email protected]"))
      .withHeaders(CONTENT_TYPE -> "application/json")
      .withJsonBody(Json.toJson(newCompany))
  ).get


  status(action) should be_==(OK)
  (contentAsJson(action) \ "id").as[Long] should be_>(1L)

}

As you can see it uses a call to route instead of calling the controller.