I am converting a considerably sized API written in Spray to Akka-Http. I’ve gotten the main conversion done, however I need to get the tests all converted over as well so I can ensure the conversion was really a success from a functionality POV.
The API has a series of unit tests and integration tests for the routes, and its in the integration tests that I’m having an issue with. In the old project we used spray-client to feed requests to the API, and I have converted this over to Akka-Http.
The problem I’m facing is with Unmarshalling of the HttpResponse I get from a request. The error I’m receiving is:
Error:(32, 25) type mismatch;
found : akka.http.scaladsl.model.HttpResponse
required: example.akka.http.User
dto = waitOnResponse(Get(endpoint))
From the following test code:
TestApi.scala
class TestApi extends Specification {
implicit val system = ActorSystem()
def waitOnResponse(request: HttpRequest): HttpResponse = {
Await.result(Http().singleRequest(request), Duration(20, "seconds"))
}
sequential
val endpoint = "http://localhost:8080/user"
val knownUuid = UUID.fromString("05ea4e86-c742-11e9-aa8c-2a2ae2dbcce4")
var dto:User = null
step {
dto = waitOnResponse(Get(endpoint))
}
"calling GET /user" should {
"return {meta:{status:OK}, user: User }" in {
dto.copy(id = knownUuid) must beEqualTo(User(knownUuid, "Test", "Akka"))
}
}
}
One of the imports contains the spray-json converters:
ConversionHelper.scala
object ConversionHelper extends DefaultJsonProtocol with SprayJsonSupport {
implicit object UUIDJsonFormat extends JsonFormat[UUID] {
def write(x: UUID) = {
require(x ne null)
JsString(x.toString)
}
def read(value: JsValue) = {
def stringToUUID(s: String): UUID = Try(UUID.fromString(s))
.recover { case t => deserializationError("Expected a valid UUID, but got " + s) }
.get
value match {
case JsString(x) => stringToUUID(x)
case x => deserializationError("Expected UUID as JsString, but got " + x)
}
}
}
implicit val metaJsonFormat = jsonFormat3(Meta)
implicit val emptyStatusResultJsonFormat = jsonFormat1(EmptyStatusResult)
implicit val userFormat = jsonFormat3(User)
implicit val userCreatedStatusResultJsonFormat = jsonFormat2(UserCreatedStatusResult)
}
I know when these tests were running under Spray, we did have some pretty funky glue-code written that I believe makes the marshalling for the tests work, that code looked like this:
Old Spray code from ConversionHelper.scala
private def unmarshalStatusResult[T:Unmarshaller](response:HttpResponse): Deserialized[T] = {
(Unmarshaller.unmarshal[T](response.entity)).left.map {
case e@ContentExpected => e
case e:MalformedContent =>
MalformedContent(s"HttpResponse: ${response} ErrorMessage: ${e.errorMessage}", e.cause)
case e:UnsupportedContentType =>
UnsupportedContentType(s"HttpResponse: ${response} ErrorMessage: ${e.errorMessage}")
}
}
def waitAndUnmarshal[T:Unmarshaller](request: HttpRequest): Deserialized[T] = {
unmarshalStatusResult(waitOnResponse(request))
}
I’m wondering how I can accomplish the same thing using Akka-Http?
I’ve created a working example of this problem here if that helps:
Any help would be greatly appreciated.
Craig