Tim Mattison

Hardcore tech

Mockito and ServletInputStreams

| Comments

I was working on a few applications that involve servlets recently and I came across a situation that initially seemed challenging to test with Mockito. I wanted to do something relatively simple which was read a Protobuf sent from a client, turn it into an object, and do some processing on it.

The question is how do you test a servlet that needs to get the input stream from a servlet request?

I found a Stack Overflow post that addresses how to do this with an older version of the ServletInputStream but doing it now requires that you override three additional methods (isFinished, isReady, and setReadListener).

My issue with this is that I don’t want to override those methods because I don’t really know what I want them to do. If I’m mocking something I want to make sure I know when and where it will be used or I want the mocking framework to return default values or throw exceptions so I know where to look when something breaks.

What I landed on was using the thenAnswer method like this:

Mocking a ServletInputStream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
byte[] myBinaryData = "TEST".getBytes();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(myBinaryData);
      
mockServletInputStream = mock(ServletInputStream.class);

when(mockServletInputStream.read(Matchers.<byte[]>any(), anyInt(), anyInt())).thenAnswer(new Answer<Integer>() {
    @Override
    public Integer answer(InvocationOnMock invocationOnMock) throws Throwable {
        Object[] args = invocationOnMock.getArguments();
        byte[] output = (byte[]) args[0];
        int offset = (int) args[1];
        int length = (int) args[2];
        return byteArrayInputStream.read(output, offset, length);
    }
});

If you need to ever mock a ServletInputStream feel free to use this code to do it. So far it has worked perfectly for me.

Comments