This rainy weekend, I was inspired by a question from hani about testing servlets. As a result I’ve added a module to Jetty to simply 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
HttpTest
class.
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.1rn"+
"Host: testerrn"+
"rn"+
"GET /context/hello HTTP/1.1rn"+
"Host: testerrn"+
"rn";
String responses = tester.getResponses(requests);
String expected=
"HTTP/1.1 200 OKrn"+
"Content-Type: text/html; charset=iso-8859-1rn"+
"Content-Length: 21rn"+
"rn"+
"<h1>Test Servlet</h1>" +
"HTTP/1.1 200 OKrn"+
"Content-Type: text/html; charset=iso-8859-1rn"+
"Content-Length: 22rn"+
"rn"+
"<h1>Hello Servlet</h1>";
assertEquals(expected,responses);


Generated Requests, Parsed Responses

Dealing with raw HTTP can be a bit verbose and difficult to test non protocol aspects. The
HttpTest
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"));


Requirements

This will be in the 6.1.0 release and is currently in 6.1-SNAPSHOT. To use these classes you need the jars for servlet-api, jetty-util, jetty, jetty-servlet-tester.


7 Comments

Anonymous · 02/06/2007 at 04:39

It’s nice to be able to test a servlet but how do you set the servletConfig for the servlet under test?

    Gawraozzora · 04/03/2012 at 10:40

    >Thank you very much for this article. It hpeeld me a great deal after a full day of trying to get JSFUnit running with embedded Tomcat.

Eamonn · 19/12/2007 at 10:36

I am trying to find out the same thing. How to set the ServletConfig/init-params programattically in Jetty. Anyone solved this one?

Anonymous · 04/03/2008 at 15:18

I have servlets which use session data to determine their output and behaviour.  Is there any way to set this up using ServletTester?

Stephen · 06/10/2009 at 17:09

If you want to set init parameters for your tests you have to use the ServletHandler class:

ServletTester tester = new ServletTester();
tester.setContextPath("/context");
ServletHandler sh = tester.addServlet("ch.primecommerce.SomeServlet", "/*");
sh.setInitParameter("name", "value");
tester.start();

See: http://www.mortbay.org/apidocs/org/mortbay/jetty/servlet/Holder.html#setInitParameter(java.lang.String,%20java.lang.String)

Caoilte O'Connor · 01/03/2011 at 15:36

Five years later this blog entry is still very useful. One problem I had, though, was with the comment advice on setting init-params. I had to do the following instead,

Field contextField = ServletTester.class.getDeclaredField("_context");
contextField.setAccessible(true);
Context context = (Context)contextField.get(tester);
context.getInitParams().put("param", "value");


URL · 30/06/2012 at 21:47

… [Trackback]…
[…] Read More: webtide.intalio.com/2006/12/unit-test-servlets-with-jetty/ […]…

Comments are closed.