簡體   English   中英

測試流式傳輸響應的 Play 框架控制器

[英]Testing Play framework controller that streams responses

我有一個發送分塊響應的控制器:

def streamDatase2t(query:String): Action[AnyContent] = Action.async {
    req =>
        serivce.getIterator(query).map(res => {
            Ok.chunked(Source.apply(res))
        })
  }

當我嘗試檢查控制器規范中的返回內容時,出現異常:

  "return 200 response with the content of the iterator" in {
      when(serivce.getIterator
      (Matchers.any[Request.DatasetLoad],
        Matchers.any[ResponseFormat], Matchers.any[Int]))
        .thenReturn(Future.successful(new FakeIterable(List("One", "Two", "Three").iterator)))

      val fakeRequest = FakeRequest.apply("GET", s"/data")

      val result = Helpers.route(fakeApp, fakeRequest).get
      checkStatus(result, OK)
      contentAsString(result) // <-- exception here ! 
    }

例外:

NoMaterializer cannot materialize
java.lang.UnsupportedOperationException: NoMaterializer cannot materialize
    at play.api.test.NoMaterializer$.materialize(Helpers.scala:732)
    at akka.stream.scaladsl.RunnableGraph.run(Flow.scala:629)
    at akka.stream.scaladsl.Source.runWith(Source.scala:106)
    at akka.stream.scaladsl.Source.runFold(Source.scala:117)
    at play.api.http.HttpEntity.consumeData(HttpEntity.scala:49)
    at play.api.http.HttpEntity.consumeData$(HttpEntity.scala:48)
    at play.api.http.HttpEntity$Chunked.consumeData(HttpEntity.scala:117)
    at play.api.test.ResultExtractors.contentAsBytes(Helpers.scala:381)
    at play.api.test.ResultExtractors.contentAsBytes$(Helpers.scala:379)
    at play.api.test.Helpers$.contentAsBytes(Helpers.scala:676)

由於異常狀態NoMaterializer cannot materialize ,您可能需要添加一個Materializer

implicit lazy val mat = ActorMaterializer()
implicit lazy val ec = instanceOf[ExecutionContext]

contentAsStringNoMaterializer作為默認參數

def contentAsString(of: Future[Result])(implicit timeout: Timeout, mat: Materializer = NoMaterializer): String

NoMaterializer只會為所有內容拋出UnsupportedOperationException ,因此請嘗試提供您自己的

implicit val actorSystem = ActorSystem("test")
implicit val materializer = ActorMaterializer()

play-scala-streaming-example演示了我們如何為流控制器編寫測試。


解決評論,考慮以下兩條路線,它們說明了嚴格和非嚴格(分塊,流式)主體之間的區別

def nonStrictBody = Action {
  val source = Source.apply(List("woo", "h", "oo"))
  Ok.chunked(source)
}

def strictBody = Action {
  Ok("woohoo")
}

在嚴格主體上調用contentAsString時,不會使用實體化器,因此NoMaterializer足夠

在 99% 的情況下,當對結果主體運行測試時,您實際上不需要物化器,因為它是一個嚴格的主體。 因此,我們並不總是需要一個隱式實體化器,而是在提供時使用一個,否則我們有一個默認的實體化器,如果使用它只會拋出一個異常。

但是,當在分塊流式主體上調用contentAsString時,就像在nonStrictBody路由中的情況一樣,我們需要提供適當的Materializer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM