如何断言 zipoutputstream 中的响应

How to assert response in zipoutputstream

我正在尝试使用 MockitoJUnitRunner 编写 JUnit。 我将文件 ID 传递给我的函数,该函数从云端下载文件并返回 zip 文件作为下载。 这是我的代码

public void getLogFile(HttpServletResponse response, String id) throws IOException {

    response.setContentType("Content-type: application/zip");
    response.setHeader("Content-Disposition", "attachment; filename=LogFiles.zip");

    ServletOutputStream out = response.getOutputStream();
    ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(out));

    zos.putNextEntry(new ZipEntry(id));

    InputStream inputStream = someDao.getFile(id);

    BufferedInputStream fif = new BufferedInputStream(inputStream);

    int data = 0;

    while ((data = fif.read()) != -1) {
        zos.write(data);
    }

    fif.close();

    zos.closeEntry();
    zos.close();
}

而我的 JUnit 函数是

@Mock
private MockHttpServletResponse mockHttpServletResponse;

anyInputStream = new ByteArrayInputStream("test data".getBytes());

    @Test
    public void shouldDownloadFile() throws IOException {

    ServletOutputStream outputStream = mock(ServletOutputStream.class);

        when(mockHttpServletResponse.getOutputStream()).thenReturn(outputStream);


 =>          when(someDao.download(anyString())).thenReturn(anyInputStream);


        controller.getLogFile(mockHttpServletResponse, id);

        verify(mockHttpServletResponse).setContentType("Content-type: application/zip");

        verify(mockHttpServletResponse).setHeader("Content-Disposition","attachment; filename=LogFiles.zip");

        verify(atmosdao).download(atmosFilePath);
    }

这个单元测试通过了,但是我想验证输出流上写的是什么,我该怎么做?因为我正在写 "test data" 来模拟 outputStream,比如

anyInputStream = new ByteArrayInputStream("test data".getBytes());

when(someDao.download(anyString())).thenReturn(anyInputStream);

mockHttpServletResponse.getContentAsString() 给我 null !

是否可以断言 MockHttpServletResponse 是使用 zipoutputStream 编写的?如果是,那我该怎么做?

谢谢。

与其模拟您的 OutputStream,您可以创建一个自定义的:

public class CustomOutputStream extends ServletOutputStream {
    private ByteArrayOutputStream out = new ByteArrayOutputStream();
    private String content;

    @Override
    public void write(int b) throws IOException {
        out.write(b);
    }

    @Override
    public void close() throws IOException {
        content = new String(out.toByteArray());
        out.close();
        super.close();
    }

    public String getContentAsString() {
        return this.content; 
    }
}

这个 class 将存储写入它的所有字节并将它们保存在 content 字段中。

然后你替换这个:

ServletOutputStream outputStream = mock(ServletOutputStream.class);

通过这个:

CustomOutputStream outputStream = new CustomOutputStream();

当您的 servlet 调用 getOutputStream() 时,它将使用自定义的,最后 getContentAsString() 将 return 您写入您的 servlet 的输出。

注意:输出是压缩的,因此字符串将包含奇怪的字符。如果您想要原始字符串,则必须解压缩它(在这种情况下,我将使用 out.toByteArray() 编辑的字节数组 return 而不是字符串,因为当您创建一个字符串时调用 string.getBytes())

时可能会遇到编码问题

我得到了我要找的东西... 这就是我使用 powerMockito 断言写入 zipoutputStream 的数据所做的。

@Test
public void ShouldAttemptToWriteDownloadedFileToZipOutputStream() throws Exception {

    InputStream anyInputStream = new ByteArrayInputStream("test data".getBytes());

    ServletOutputStream outputStream = mock(ServletOutputStream.class);

    BufferedOutputStream bufferedOutputStream = Mockito.mock(BufferedOutputStream.class);
    PowerMockito.whenNew(BufferedOutputStream.class).withArguments(outputStream).thenReturn(bufferedOutputStream);

    ZipOutputStream zipOutputStream = Mockito.mock(ZipOutputStream.class);
    PowerMockito.whenNew(ZipOutputStream.class).withArguments(bufferedOutputStream).thenReturn(zipOutputStream);

    BufferedInputStream bufferedInputStream = new BufferedInputStream(anyInputStream);
    PowerMockito.whenNew(BufferedInputStream.class).withArguments(anyInputStream).thenReturn(bufferedInputStream);

    subjectUnderTest.getLogFile(mockHttpServletResponse, "12345");

    int data = 0;

    while ((data = bufferedInputStream.read()) != -1) {

        verify(zipOutputStream).write(data);
    }
}

感谢雨果的帮助!