J2EEUnit provides a
sample application that
shows how to write test cases for unit testing servlet methods. You
should have a look at this sample application as it gives thorough
example. However, this section only focuses on explaining the principle
by showing a very simple example.
For the sake of simplicity let's imagine we have a servlet called
SimpleServlet which has a single method :
registerUser() : Gets the user name from a HTTP request
parameter, save it in the HTTP Session and send a Cookie back to the
client with the user name in it. The returned HTML prints the name
that was retrieved from the HTTP request's parameter.
Step 1 : The SimpleServlet's code
Here is the code to unit test :
package sample;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class SimpleServlet extends HttpServlet
{
public void doGet(HttpServletRequest theRequest, HttpServletResponse theResponse) throws IOException
{
PrintWriter pw = theResponse.getWriter();
theResponse.setContentType("text/html");
pw.print("<html><head/><body>");
pw.print("<h1>Your name is " + registerUser(theRequest, theResponse) + "</h1>");
pw.print("</body></html>");
}
public String registerUser(HttpServletRequest theRequest, HttpServletResponse theResponse)
{
// Get the user name from the HTTP request's parameter
String name = theRequest.getParameter("USER_NAME");
// Save it in the session
HttpSession session = theRequest.getSession();
session.putValue("NAME", name);
// And return a cookie
Cookie cookie = new Cookie("ID", name);
theResponse.addCookie(cookie);
return name;
}
}
Step 2 : Unit testing strategy
Notice that we mentionned we were going to test the
registerUser() method but nothing was said about the
doGet() method ... Indeed, unit testing the
doGet() (or doPost()) is not completely
relevant. This kind of test is actually more a functional test (you
can use a framework such as
HttpUnit for
doing this). However, for some simple cases it is not always
easy to differentiate between unit test and functional test, you
might want the test to be part of your unit test suite or it is a
simple case that do not need to set up a functional test framework.
For these cases, J2EEUnit support asserting the output stream returned
from your servlet, so it is possible to unit test the
doGet() type methods, as demonstrated below.
However, you should try to not put any logic in your
doGet and doPost() methods. You should
rather delegate any code logic to other methods (such as the
registerUser() method is the sample below). It is called
the facade pattern. If you do it this way, you can easily unit test
your logic code methods one by one.
Step 3 : The test code
public class TestSimpleServlet extends ServletTestCase
{
[standard JUnit code. See the using section]
/**
* Sets the HTTP request parameter that will be available in the test
* method.
*/
public void beginRegisterUser(ServletTestRequest theRequest)
{
theRequest.addParameter("USER_NAME", "Vincent");
}
/**
* Unit test the registerUSer method.
*/
public void testRegisterUser()
{
// Instantiate the class to test
SimpleServlet servlet = new SimpleServlet();
// Call the method to test
String name = servlet.registerUser(request, response);
// Verify that it returns the correct name
assertEquals("Vincent", name);
// Verify that the name has been put in the session
assertEquals("Vincent", (String)session.getValue("NAME"));
}
/**
* Verify that a cookie has been returned
*/
public void endRegisterUser(HttpURLConnection theConnection)
{
Hashtable cookies = AssertUtils.getCookies(theConnection);
Vector list = (Vector)cookies.get("ID");
assert(list.size() == 1);
ClientCookie cookie = (ClientCookie)list.elementAt(0);
assertEquals("ID", cookie.getName());
assertEquals("Vincent", cookie.getValue());
}
/**
* Test the output stream returned by the <code>doGet()</code> method.
*/
public void testDoGet()
{
SimpleServlet servlet = new SimpleServlet();
servlet.doGet(request, response);
}
/**
* Test the output stream returned by the <code>doGet()</code> method.
*/
public void endDoGet(HttpURLConnection theConnection)
{
assertEquals("<html><head/><body><h1>Your name is Vincent</h1></body></html>",
AssertUtils.getResponseAsString(theConnection));
}
}
Notice that in the endRegisterUser() and
endDoGet() test methods we use methods from a helper
class provided by J2EEUnit to help retrieve cookies sent back from
the servlet and to help assert the returned servlet output stream.
For unanswered questions, see the section on
using J2EEUnit and the
FAQ.