3

So, I have a set of Akka Http routes written in scala. Which looks like this

val route: Route = {
  handleRejections(PrimaryRejectionHandler.handler) {
    handleExceptions(PrimaryExceptionHandler.handler) {
      cors() {
        encodeResponseWith(Gzip) {
          pathPrefix("v1") {
            new v1Routes().handler
          } ~
            path("ping") {
              complete("pong")
            }
        }
      }
    }
  }
}

Now I want to test this using scala-test and akka testkit.

class HttpRouteTest extends WordSpec with Matchers with ScalatestRouteTest {

  "GET /ping" should {

    "return 200 pong" in new Context {
      Get("/ping") ~> httpRoute ~> check {
        responseAs[String] shouldBe "pong"
        status.intValue() shouldBe 200
      }
    }
  }

  trait Context {
    val httpRoute: Route = new HttpRoute().route
  }

}

Now since, I am encoding my responses with gzip in the route, the test is getting gibberish when it's trying to convert to string. As a result the test does not pass.

Is there any solution to this? Thanks in advance.

debduttoc
  • 304
  • 2
  • 9
  • Try using Mockito where you can actually mock the response for certain values of string. In such a case for a certain request, mock the response by giving in mocked gzip file and verify in your test case if you get the same mocked gzip object – Chaitanya Oct 23 '18 at 11:11

2 Answers2

2

For anyone who bumps into this.

This is how I solved the problem. Firstly I structured the unit test packages with the same name of the module it is testing.

I made a BaseService that will be used in all tests which looks like this

trait BaseServiceTest extends WordSpec with Matchers with ScalatestRouteTest with MockitoSugar {

  def awaitForResult[T](futureResult: Future[T]): T =
    Await.result(futureResult, 5.seconds)

  def decodeResponse(response: HttpResponse): HttpResponse = {
    val decoder = response.encoding match {
      case HttpEncodings.gzip ⇒
        Gzip
      case HttpEncodings.deflate ⇒
        Deflate
      case HttpEncodings.identity ⇒
        NoCoding
    }

    decoder.decodeMessage(response)
  }
}

Then using this I wrote my tests like so

class UserTest extends BaseServiceTest {

  "GET /user" should {

    "return user details with 200 code" in new Context {

      Get("/") ~> userRoute ~> check {
        val decodedResponse = getBody(decodeResponse(response))

        decodedResponse.user.name.isDefined shouldBe true
        decodedResponse.user.age.isDefined shouldBe true
        decodedResponse.user.city.isDefined shouldBe true
        status.intValue() shouldBe 200
      }
    }
  }

  trait Context {
    val userRoute: Route = UserRoute.route
  }

  def getBody(resp: HttpResponse): UserResponse = {

    import UserResponseJsonProtocol._ // Using spray-json for marshalling protocols

    Await.result(Unmarshal(resp).to[UserResponse], 10.seconds)
  }
}

Hope this helps. Thanks!

debduttoc
  • 304
  • 2
  • 9
0

Currently akka-http doesn't provide automatic decoding of responses client side and the same seems to be true for the testkit.

This means that if you need to add the decompression handling yourself. That said most of the actual decoding code is already bundled inside akka and you only need some glue code as described in the [Akka HTTP documentation].

nivox
  • 2,060
  • 17
  • 18