Akka Http测试Gzip响应

时间:2018-10-23 10:40:25

标签: scala testing gzip akka-http akka-testkit

因此,我有一组用Scala编写的Akka Http路由。看起来像这样

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

现在,我想使用scala-test和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
  }

}

现在,由于我在路由中使用gzip编码响应,因此尝试将其转换为字符串时测试变得乱码。结果测试没有通过。

对此有什么解决办法吗? 预先感谢。

2 个答案:

答案 0 :(得分:0)

当前akka-http尚不提供客户端的响应自动解码功能,并且对于测试包来说也是如此。

这意味着如果您需要自己添加减压处理。那就是说,大多数实际的解码代码已经捆绑在akka中,并且您只需要[[Akka HTTP documentation]中描述的一些粘合代码即可。

答案 1 :(得分:0)

任何碰到这个的人。

这就是我解决问题的方式。 首先,我使用与要测试的模块相同的名称来构造单元测试包。

我制作了一个BaseService,它将在所有看起来像这样的测试中使用

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

然后用这个我像这样写了我的测试

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

希望这会有所帮助。谢谢!