Ali
Ali

Reputation: 1590

How to assert response in zipoutputstream

I am trying to write JUnit using MockitoJUnitRunner. I am passing file id to my function which is downloading file from cloud and returning zip file as download. here is my code

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();
}

And my JUnit function is

@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);
    }

This unit test is passing but I want to verify what is written on outputStream, how can I do it ? as I am writing "test data" to mocked outputStream like

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

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

mockHttpServletResponse.getContentAsString() is giving me null !

Is it possible to assert MockHttpServletResponse which is written using zipoutputStream ? if yes then how can i do it ?

Thanks.

Upvotes: 1

Views: 3289

Answers (2)

Ali
Ali

Reputation: 1590

I got what I was looking for... This is what I did to assert data written to zipoutputStream using powerMockito.

@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);
    }
}

Thanks Hugo for your help !

Upvotes: 1

user7605325
user7605325

Reputation:

Instead of mocking your OutputStream, you could create a custom one:

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; 
    }
}

This class will store all the bytes written to it and keep them in the content field.

Then you replace this:

ServletOutputStream outputStream = mock(ServletOutputStream.class);

by this:

CustomOutputStream outputStream = new CustomOutputStream();

When your servlet calls getOutputStream(), it will use the custom one, and in the end getContentAsString() will return you the output that was written to your servlet.

Note: the output is zipped, so the String will contain strange characters. If you want the original string, you'll have to unzip it (and in this case I'd use the byte array returned by out.toByteArray() instead of the String, because when you create a String this way you can have encoding problems when calling string.getBytes())

Upvotes: 1

Related Questions