在测试使用枚举器返回分块响应的Action时,我遇到了Play 2.3.7的问题:
def text = Action {
Ok.chunked(Enumerator("abc"))
}
使用curl http://localhost:9000/text
我得到了预期的结果:abc
但是接下来的测试:
class ApplicationSpec extends Specification {
"Application" should {
"stream text" in new WithApplication{
val request = route(FakeRequest(GET, "/text")).get
contentAsString(request) mustEqual "abc"
}
}
}
因比较错误而失败:
[info] Application should
[info] x stream text
[error] '3
[error] abc
[error] 0
[error]
[error] ' is not equal to 'abc' (ApplicationSpec.scala:31)
这些额外角色来自哪里?我怀疑这可能是FakeRequest和Enumerators的问题?在Action中连接的枚举器的更复杂的情况下,枚举器生成的内容之间会混合使用字符。
答案 0 :(得分:4)
这个已知问题已针对即将推出的Play 2.4修复,但在2.3.x中不可用。额外的字符是从分块编码中引入的。它们表示每个HTTP响应主体开头的十六进制块长度。旧的测试助手只是将它们连接在一起,而不是将它们除去。
我一直在使用以下代码解决2.3.x上的问题(感谢marcuslinke的帖子来自github issue):
import scala.concurrent._
import scala.concurrent.duration._
import play.api.mvc._
import play.api.libs.iteratee._
import akka.util.Timeout
def contentAsBytes(of: Future[Result])(implicit timeout: Timeout): Array[Byte] = {
val result = Await.result(of, timeout.duration)
val eBytes = result.header.headers.get(TRANSFER_ENCODING) match {
case Some("chunked") => result.body &> Results.dechunk
case _ => result.body
}
Await.result(eBytes |>>> Iteratee.consume[Array[Byte]](), timeout.duration)
}
我在测试(specs2)中使用的是这样的:
new String(contentAsBytes(result)) must equalTo("expected value")
作为参考,这里是合并为master的pull request。