Play2测试中是否存在使用FakeRequests和分块响应(Enumerator)的错误?

时间:2015-02-11 18:37:10

标签: testing playframework chunked

在测试使用枚举器返回分块响应的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中连接的枚举器的更复杂的情况下,枚举器生成的内容之间会混合使用字符。

1 个答案:

答案 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