I'm building an application on play_2.9.1-2.0.3 and testing with specs2_2.9.1-1.7.1 (which came bundled with play). I have an action that looks like this:
def createPoll() = Action { request =>
request.body.asJson.map {jsonBod =>
Poll.fromJsonValue(jsonBod).fold(
thrown => CommonResponses.invalidCreatePollRequest(this),
poll => (CommonResponses.createdPoll(poll, this))
)}.getOrElse(CommonResponses.expectingJson(this))
}
This works as expected when I send it a message from curl, but in my specs2 test I get this exception:
ClassCastException: java.lang.String cannot be cast to play.api.mvc.AnyContent(PollController.scala:16)
where line 16 is:
def createPoll() = Action { request =>
Here is the relevant part of the test:
routeAndCall(
FakeRequest(
PUT, controllers.routes.PollController.createPoll().url,
FakeHeaders(),
"{\"userId\":\"%s\",\"title\":\"%s\"}".format(userId, title)
).withHeaders(("Content-type", "application/json"))
)
If I change the createPoll
def to: def createPoll() = Action(parse.tolerantText) {
then I can make it work from the specs2 test.
Does anyone know what I'm doing wrong? Ideally I would like to use the parse.json body parser but I want to be able to use specs and not just curl for testing. Thanks
The apply method on Action takes a Request[AnyContent] => Result
. The parametrized type of the FakeRequest is the type of the fourth parameter (the body of the request). Given these, the problem is quite obvious: you're trying to pass a Request[String]
as an input to a function that takes a Request[AnyContent]
. Hence the class cast exception. All you need to do is create a FakeRequest with an AnyContentAsJson
(A subtype of AnyContent
) like this:
import play.api.libs.json.Json.parse
FakeRequest(
PUT, controllers.routes.PollController.createPoll().url,
FakeHeaders(),
AnyContentAsJson(parse("{\"userId\":\"%s\",\"title\":\"%s\"}".format(userId, title)))
)