2

我想用MockMvc测试一个没有 Spring 上下文的 Spring 控制器。此控制器通过将内容写入响应的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)
4

1 回答 1

0

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

Java 文档:

注意:方法在这里没有显式关闭底层流;但是,这个映射器使用的 JsonFactory 可能会根据其设置选择关闭流(默认情况下,当我们构造的 JsonGenerator 关闭时,它会尝试关闭它)。

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

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

try {
    writer.flush();
} catch (IOException e) {
    logger.info("Stream closed in writeValue()", e);
}
于 2016-01-07T17:30:42.683 回答