Reputation: 2876
I've been struggling several hours and every time I send a FakeRequest, it seems that the FakeApplication receives an empty body. However, if I try to run the play application and I send a normal request to localhost, everything works as expected, I receive the text I sent as a response.
Another test of the test that I have done is sending a custom response (not the same it receives) from the controller, like a string "a".
My test code looks like:
val controller = app.injector.instanceOf(classOf[CreateRecordController])
val js = Json.obj()
val result = controller.apply().apply(
FakeRequest(POST, "/api/v1/record/")
.withHeaders(Headers(CONTENT_TYPE -> "application/json"))
.withJsonBody(js)
)
val content = contentAsJson(result)
info.apply(s"content was $content")
The last statement prints: "content was" and an html page saying: "For request 'POST /api/v1/record/' [Invalid Json: No content to map due to end-of-input at [Source: akka.util.ByteIterator$ByteArrayIterator$$anon$1@5fdfe8cf; line: 1, column: 0]]" -> So the content is empty.
My action handler in the controller is:
def apply: Action[JsValue] = Action.async(parse.json) { implicit request =>
Future.successful(BadRequest(request.body).withHeaders("Content-type" -> "application/json"))
}
Am I missing something?
Play version: 2.6.2
Upvotes: 4
Views: 2224
Reputation: 599
Here you go, give this a read first - https://www.playframework.com/documentation/2.6.x/ScalaEssentialAction
Controller
def work = Action.async(parse.json) { implicit request =>
Future.successful(BadRequest(request.body).withHeaders((CONTENT_TYPE, "application/json")))
}
Test
class ApplicationSpec extends PlaySpec with Results with GuiceOneAppPerTest with Injecting {
"Application" should {
"work" in {
implicit lazy val materializer: Materializer = app.materializer
val controller = new Application(inject[ControllerComponents])
val body = Json.obj()
val result = call(controller.work(), FakeRequest(POST, "/work").withHeaders((CONTENT_TYPE, "application/json")).withJsonBody(body))
contentAsJson(result) mustBe body
}
}
}
Upvotes: 3
Reputation: 2876
It seems that if the content is passed to the FakeRequest at construction time it works as expected. What I've seen is that if I pass a JsValue as the body at construction time, the FakeRequest is of type FakeRequest[JsValue] which works fine. But if the method .withBodyAsJson is used, the type becomes FakeRequest[AnyContentAsJson]. It may be a bug.
Upvotes: 2