如何使用 MockMvc 测试具有流式内容的控制器?

How to test a controller with streamed content with MockMvc?

我想测试一个 Spring 控制器,没有 Spring 上下文,使用 MockMvc。 此控制器 streams 通过将内容写入响应的 OutputStream

控制器代码如下:

@RequestMapping(method = GET, value = "/file")
public void getFile(HttpServletResponse response) throws IOException {
    response.setHeader("Content-Disposition", "attachment; filename=file.json");
    ObjectWriter objectWriter = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).writer();

    Item item = new Item();
    List<Item> items = new ArrayList<>();
    items.add(item);

    try (Writer bufferedWriter = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()))) {
        objectWriter.writeValue(bufferedWriter, items);
        bufferedWriter.flush();
    }
}

这是测试:

@Test
public void getFile_ok() throws Exception {
    mockMvc.perform(get(END_POINT + "/file").accept(MediaType.APPLICATION_JSON))
           .andExpect(status().isOk());
}

此控制器运行良好,但单元测试失败并出现 IOException:

java.io.IOException: Stream closed
    at java.io.BufferedWriter.ensureOpen(BufferedWriter.java:116)
    at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:126)
    at java.io.BufferedWriter.flush(BufferedWriter.java:253)

实际上 objectWriter.writeValue(bufferedWriter, items); 试图关闭流。

Javadoc:

Note: method does not close the underlying stream explicitly here; however, JsonFactory this mapper uses may choose to close the stream depending on its settings (by default, it will try to close it when JsonGenerator we construct is closed).

在运行时,它不会关闭它,但在我的测试中,它会关闭,下一行 bufferedWriter.flush(); 只是发送 IOEception.

所以为了修复它,我用这种方式添加了一个 try/catch:

try {
    writer.flush();
} catch (IOException e) {
    logger.info("Stream closed in writeValue()", e);
}