How to test a Servlet

The jetty infrastructure can be use to test servlets with an embedded server configured by the ServletTester class. The HTTP requests and responses for testing can be generated and parsed with the HttpTester class.

The embedded server uses a special local connector, and thus avoids the need to open sockets in order to test the servlet.

An example of a test harness that uses these classes is ServletTest.

Setting up the tester

The ServletTester can configure a single context. Servlets and Filters may be added to the context by class name or class instance. Context attributes, a resource base or a classloader may optionally be set. eg.

ServletTester tester=new ServletTester();
tester.setContextPath("/context");
tester.addServlet("come.acme.TestFilter", "/*");
tester.addServlet(TestServlet.class, "/servlet/*");
tester.addServlet(HelloServlet.class, "/hello");
tester.addServlet("org.mortbay.jetty.servlet.DefaultServlet", "/");
tester.start();

Raw HTTP requests and responses.

The ServletTester takes a string containing requests and
returns a string containing the corresponding responses (eventually byte arrays will be supported for testing character encoding and binary content). More than one request can be pipelined and multiple responses will be returned if persistent connection conditions are met. eg.

String requests=
   "GET /context/servlet/info?query=foo HTTP/1.1\r\n"+
   "Host: tester\r\n"+
   "\r\n"+         
   "GET /context/hello HTTP/1.1\r\n"+
   "Host: tester\r\n"+
   "\r\n";
            
String responses = tester.getResponses(requests);
        
String expected=
   "HTTP/1.1 200 OK\r\n"+
   "Content-Type: text/html; charset=iso-8859-1\r\n"+
   "Content-Length: 21\r\n"+
   "\r\n"+
   "<h1>Test Servlet</h1>" +
         
   "HTTP/1.1 200 OK\r\n"+
   "Content-Type: text/html; charset=iso-8859-1\r\n"+
   "Content-Length: 22\r\n"+
   "\r\n"+
   "<h1>Hello Servlet</h1>";
            
assertEquals(expected,responses);

Generated Requests and Parsed Responses

Dealing with raw HTTP can be a bit verbose and difficult to test non protocol aspects. The HttpTester class allows for simple generation of requests and parsing of response (it can also parse requests and generate responses). eg.

HttpTester request = new HttpTester();
HttpTester response = new HttpTester();
request.setMethod("GET");
request.setHeader("Host","tester");
request.setURI("/context/hello/info");
request.setVersion("HTTP/1.0");

response.parse(tester.getResponses(request.generate()));

assertTrue(response.getMethod()==null);
assertEquals(200,response.getStatus());
assertEquals("<h1>Hello Servlet</h1>",response.getContent());

Once setup, the HttpTester instances may be reused and only the parts that change need to be
set for subsequent requests. eg.

        
request.setURI("/context");
response.parse(tester.getResponses(request.generate()));
assertEquals(302,response.getStatus());
assertEquals("http://tester/context/",response.getHeader("location"));