Search code examples
scalaplayframeworkspecs2

ClassCastException On Action When Invoked From Specs2


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


Solution

  • 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)))
        )