[英]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]
contentAsString
将NoMaterializer
作为默认参数
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.