When writing custom servlets, it can be quite useful to unit test them. In my case, I used a combination of testng and mockito. The basic idea is simple; mock a HttpServletRequest, and a HttpServletResponse and pass them to the custom servlet. There is a bit more too it, so here's an example.
final HttpServletRequest httpServletRequest = mock(HttpServletRequest.class); when(httpServletRequest.getPathInfo()).thenReturn("/lineup/world.xml"); final HttpServletResponse httpServletResponse = mock(HttpServletResponse.class); final StubServletOutputStream servletOutputStream = new StubServletOutputStream(); when(httpServletResponse.getOutputStream()).thenReturn(servletOutputStream); final ServletConfig servletConfig = mock(ServletConfig.class); when(servletConfig.getInitParameter("defaultPool")).thenReturn("testpool1");
This sets up an HttpServletRequest, an HttpServletResponse, a ServletConfig where i can pass in parameters that the container would have read from web.xml, and a "StubServletOutputStream", which is just a convenient wrapper around a ByteArrayOutputStream.
My StubServletOutputStream looks like this:
public class StubServletOutputStream extends ServletOutputStream { public ByteArrayOutputStream baos = new ByteArrayOutputStream(); public void write(int i) throws IOException { baos.write(i); } }
It's necessary to init() the servlet, something the container would normally do:
final MyServlet myServlet = new MyServlet(); myServlet.init(servletConfig);
Finally; I invoke my servlet, and check the output:
restCacheServlet.doGet(httpServletRequest, httpServletResponse); final byte[] data = servletOutputStream.baos.toByteArray(); Assert.assertNotNull(data); Assert.assertTrue(data.length > 0);
August 21, 2013 - 2:58 am
hi, nice trick! I have introduced a minor change so the class looks like this:
public class FakeServletOutputStream extends ServletOutputStream {
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
public void write(int i) throws IOException {
baos.write(i);
}
public String getContent() {
return baos.toString();
}
}
August 24, 2013 - 6:59 pm
Nice work! Thanks!
November 24, 2013 - 11:07 am
Than you Tomek! It worked!
February 18, 2014 - 11:51 am
Is there a way to setup the context too? In my app, i use the context to store Database things like status of something , so i dont have to query the db everytime i open my formulars, they change never and now i want to test an method like getIdFromRequest or getStatusFromContext. Productioncode works but i have to refactor it and i have no tests, just a few integration tests. Maybe there is a tweak to init the context inside my servlet .
greetings Lordi
June 9, 2014 - 2:17 pm
Thanks. It worked and helped me :).
May 31, 2017 - 8:08 am
Thanks Man. It worked for me.
This code is pure gold. I was struck for 3hrs on mocking invoking the servlet, and finally it worked.
Thanks a lot
July 23, 2017 - 1:51 pm
You’re quite welcome.
September 5, 2018 - 9:04 am
Thanks a lot. It helped me greatly.
November 15, 2018 - 12:29 pm
Thanks a lot for this 🙂
December 6, 2019 - 10:08 am
Very useful and interesting. Thankyou for sharing this Great article