MockMvc和流端点-流关闭后的额外字节



我在一个小型Scala应用程序中使用spring-test和spring-boot。(很抱歉我的介绍很长,问题很短!)

到目前为止,一切都很顺利,直到我决定修改其中一个端点以支持流。为此,我将HttpServletResponse对象添加到请求处理程序中,并使用Apache Commons的IOUtils.copy复制源数据。

@RequestMapping(value = Array("/hello"), method = Array(RequestMethod.GET))
def retrieveFileForVersion(response:HttpServletResponse) = {
    val is = getAnInputStream
    val os = response.getOutputStream
    try {
      IOUtils.copy(is, os)
    } finally {
      IOUtils.closeQuietly(is)
      os.flush()
      IOUtils.closeQuietly(os)
    }
  }
}

这似乎工作得相当好。我可以从端点检索二进制数据,并验证其MD5校验和是否与源数据的MD5校验和匹配。

然而,我注意到在spring测试的MockMvc中使用REST控制器时不再是这种情况。实际上,当通过MockMvc执行请求时,响应实际上比通常大4个字节。因此,一些简单的断言会失败:

@Test
def testHello() =  {
    //  ... snip ... read the binary file into a byte array
    val bytes = IOUtils.toByteArray(...)
    val result = mockMvc.perform(get("/hello")).andExpect(status.isOk).andReturn
    val responseLength = result.getResponse.getContentAsByteArray.length
    //  TODO - find out why this test fails!
    assert(responseLength == bytes.length, s"Response size: $responseLength, file size: ${bytes.length}")
    assert(Arrays.equals(result.getResponse.getContentAsByteArray, bytes))
}

使用调试器,我能够确定MockMvc是附加到响应OutputStream,即使它已经使用IOUtils.closeQuietly关闭。实际上,它附加了请求处理程序的返回值,该值是OutputStream中的字节数(实际上来自IOUtils.closeQuietly)。

为什么MockMvc附加到OutputStream后,它已经关闭?这是一个错误,还是我使用库不正确?

根据返回类型、方法注释和某些情况下的输入参数,可以以不同的方式解释控制器方法的返回值。

在@RequestMapping注释和参考文档中详细列出了这一点。对于流的情况,将HttpServletResponse作为输入参数的组合(顺便也可以使用OutputStream)和void作为返回类型,向Spring MVC表明您已经自己处理了响应。

相关内容

  • 没有找到相关文章

最新更新