Unit Testing Servlets: A simple test for a complex servlet
Testing Java servlets reliably can often be difficult. Generally the main business logic is contained in a different class which can be tested in isolation, but in some cases it is necessary to have some logic in the servlet itself. It’s also nice to have a quick sanity check that the servlet is loading as it should be and generating the correct responses.
Servlets, like many other things that have several reliant services, can be difficult to test as they tend to require a full web stack, such as an application server and database. These reliant services can often fail resulting in unreliable tests, which can be a nightmare in a continuous integration system. Thankfully the Jetty servlet tester can help overcome these issues.
The Jetty servlet tester library uses an embedded Jetty application server and can be used to write unit tests that test the functionality of our application server while mocking out any services the tests rely on.
Using the servlet tester is pretty straightforward. First, make sure the servlet tester jar is on the Java classpath either by manually adding it or adding it as a build dependency; you can find it in the Maven central repository here.
Using Maven, Gradle or similar to add it to the classpath is by far the easier option as there are some transitive dependencies, such as the servlet API, that the servlet tester relies on.
Once the jars are on our classpath we can start writing some tests.
For this example I have created a very complex servlet – it simply responds to every request with “It works” and sets a header field that we can test. Using the servlet tester is pretty straightforward. In our test we first create the server and add our servlet to it, specifying the context for the servlet.
ServletTester servletTester = new ServletTester(); servletTester.addServlet(com.caplin.example.MyServlet.class, "/validUrl"); servletTester.start();
We then create a request to send to the servlet, make the request, and retrieve the content.
HttpTester request = new HttpTester(); request.setMethod("GET"); request.setURI("/validUrl"); request.setVersion("HTTP/1.0"); HttpTester response = new HttpTester(); response.parse(servletTester.getResponses(request.generate()));
Once we have the response we can then perform several checks on the response code, the content and various other headers.
assertEquals(200,response.getStatus()); assertEquals("It works",response.getContent()); assertEquals("yes",response.getHeader("did-it-work"));
There we have it, a quick test for our very complex servlet. These unit tests can then be extended to work with real life scenarios, perhaps reading expected content from a file, mocking out any other services such as databases and still run quickly and reliably.
You can download the example source code including a servlet tester utility class here.