Reputation: 7986
I'm trying to test a play framework 2.5.10 controller that uses a custom bodyparser and JSON validator:
class MessagingController {
def validateJson[A : Reads] = parse.json.validate(
_.validate[A].asEither.left.map(e => BadRequest(JsError.toJson(e)))
)
def createMessageThread() = Action(validateJson[InboundMessageThread]) { request =>
Ok("OK") }
}
When I run a simple test case on this I get an error:
For request 'POST /api/v1/messageThreads' [Invalid Json: No content to map due to
end-of-input at [Source: akka.util.ByteIterator$ByteArrayIterator$$anon$1@5693d1d2; line: 1, column: 0]]
The test is:
val fakeRequest = FakeRequest()
.withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
.withBody(Json.parse(
s"""
|{
| "participants": [
| {"id": $currentUserId, "isAdmin": false}
| ],
| "isGroupThread": false
|}
""".stripMargin))
val result = messagingController.createMessageThread()(fakeRequest).run()
status(result) mustBe OK
If I change the controller's action to just Action
and then validate the JSON in the body of the controller it works. I don't want to do that though because lots of my REST controllers need to parse JSON and using validateJson[T]
reduces boilerplate. The code also works if I submit the same payload using curl.
How can I test this controller?
Upvotes: 1
Views: 1086
Reputation: 7986
The following sort of request works:
val request = FakeRequest()
.withHeaders(CONTENT_TYPE -> "application/json")
.withBody(Json.fromJson[Place](body).get)
Upvotes: 1
Reputation: 4396
Rather than calling the Action with a JSON bodyparser, I'd suggest calling it with an ActionBuilder using an AnyContent
body parser and then calling Json.validate from inside the body -- from there, you get a stack trace and see what's failed:
class MessagingController {
def createMessageThread() = Action { request =>
request.json.validate[MessageThread] {
case JsError(e) =>
logger.error(s"Failure parsing because $e")
BadRequest(JsError.toJson(e))
case JsSuccess(e) =>
Ok("OK")
}
}
}
Upvotes: 0
Reputation: 754
Try this, hope this helps
val postRequest = FakeRequest(POST, "/route/to/hit").withJsonBody(Json.obj(
"participants" -> Json.arr(Json.obj("id" -> "currentUserId", "isAdmin" -> false)),
"isGroupThread" -> false
))
val result = await(messagingController.createMessageThread()(postRequest))
status(result) must be equalTo (FORBIDDEN)
Upvotes: 0