dgrandes
dgrandes

Reputation: 1207

Using pattern matching with Specs2 and Play in Scala

I have a simple problem with Scala/Play 2.0 and Specs.

This is my test

"Server" should {
"return a valid item with appropriate content type or a 404" in {
        val Some(result) = routeAndCall(FakeRequest(GET, "/item/1"))
        status(result) match {
            case 200 => contentType(result) must beSome("application/json")
            case 404 => true
            case _ => throw new Exception("The Item server did not return either a 200 application/json or a 404")
        }
        //false   --> It only compiles if I add this line!
 }
}
}

This doesnt compile because of the following:

 No implicit view available from Any => org.specs2.execute.Result.
[error]     "return a valid item with appropriate content type or a 404" in {
[error]                                                                  ^
[error] one error found

So Im thinking status(result) match is evaluating to Any hence the error. How should I specify that its result type is Result given that I am having a default case with a false return value?

Upvotes: 2

Views: 1613

Answers (2)

Eric
Eric

Reputation: 15557

I want to add one precision to Andrea's answer.

Each branch indeed needs to give rise to a common type that can be converted to Result. The first branch type is MatchResult[Option[String]] and the second and third types are of type Result.

There is a way to avoid the type annotation by using a MatchResult instead of a Result. ok and ko are 2 MatchResults, equivalent to success and failure, and can be used here:

"return a valid item with appropriate content type or a 404" in {
  val Some(result) = routeAndCall(FakeRequest(GET, "/item/1"))
  status(result) match {
    case 200 => contentType(result) must beSome("application/json")
    case 404 => ok
    case _   => ko("The Item server did not return ... or a 404")
  }
}

Upvotes: 6

user500592
user500592

Reputation:

You should ensure that each branch of the match results something convertible to specs2 Result. So, instead of true you can use success and instead of throw new Exception("...") use failure("...").

Edit: It seems you also have to help Scalac out a bit. Add parentheses around the match and ascribe the type like this:

import org.specs2.execute.Result

"return a valid item with appropriate content type or a 404" in {
    val Some(result) = routeAndCall(FakeRequest(GET, "/item/1"))
    (status(result) match {
      case 200 => contentType(result) must beSome("application/json")
      case 404 => success
      case _ => failure("The Item server did not return either a 200 application/json or a 404")
    }): Result
 }

Upvotes: 4

Related Questions