Spray unmarshalling generic type

501 views Asked by At

I'm using spray-client to generate http requests to my server in e2e tests. I also use specs2 to test for the desired response from the server. And everything works fine. I've built some custom specs2 matchers to simplify my test code. My test looks like this:

val response = get(<server_endpoint_url>)

response must beSuccessfulWith(content = expected_data)

I have a trait that somewhat simplifies the usage of spray in the test itself:

trait SprayTestClientSupport {
    implicit val system = ActorSystem()
    import system.dispatcher // execution context for futures

    val pipeline: HttpRequest => Future[HttpResponse] = sendReceive

    def get(url: String): Future[HttpResponse] = pipeline(Get(url))
}

I also have a trait where I define the custom matchers I use in the test:

trait SprayTestClientSupport extends ShouldMatchers with SprayJsonSupport with DefaultJsonProtocol {
    def beSuccessfulWith(content: Seq[Int]): Matcher[Future[HttpResponse]] = 
      beSuccessful and haveBodyWith(content)

    def haveBodyWith(content: Seq[Int]): Matcher[Future[HttpResponse]] = 
      containTheSameElementsAs(content) ^^ { f: Future[HttpResponse] =>
        Await.result(f, await).entity.as[Seq[Int]].right.get
      }

    def beSuccessful: Matcher[Future[HttpResponse]] =
      ===(StatusCode.int2StatusCode(200)) ^^ { f: Future[HttpResponse] =>
        Await.result(f, await).status 
      } 
}

My problem starts when I try to make the matchers more general and support any Scala type for instance. I define something like this:

def haveBodyWith[T: TypeTag](content: T): Matcher[Future[HttpResponse]] = 
  ===(content) ^^ { f: Future[HttpResponse] => 
    Await.result(f, await).entity.as[T].right.get
}

But then I get the following error message:

Error:(49, 86) could not find implicit value for parameter unmarshaller: spray.httpx.unmarshalling.Unmarshaller[T]
===(content) ^^ { (f: Future[HttpResponse]) => { Await.result(f, await).entity.as[T].right.get } }

Is there anything simple that I'm missing?

Thanks!

P.S.
I use the following spray versions:
spray-client_2.10 -> 1.3.3
spray-can_2.10    -> 1.3.3
spray-http_2.10   -> 1.3.3
spray-httpx_2.10  -> 1.3.3
spray-util_2.10   -> 1.3.3
spray-json_2.10   -> 1.3.2
1

There are 1 answers

0
Eric On BEST ANSWER

You need to add a constraint to your T parameter

def haveBodyWith[T: TypeTag : Unmarshaller](content: T): Matcher[Future[HttpResponse]] = 
  ===(content) ^^ { f: Future[HttpResponse] => 
     Await.result(f, await).entity.as[T].right.get
}