JaVa
   

Testing Servlets and Filters with Cactus

If you read the previous chapter, then you saw how the various pieces of a Cactus test fit together. This chapter shows you how to use Cactus to test specific J2EE components, such as servlets and filters. Later chapters cover testing JSP custom tags, and EJBs.

Testing Servlets

As you saw in the previous chapter, developers extend one of the three Cactus TestCases (ServletTestCase, FilterTestCase, or JspTestCase) to create their own test case. Testing servlets with Cactus requires that you extend ServletTestCase. ServletTestCase adds features to support the testing of methods that depend on objects made available in the servlet container. Note that most of the principles that apply to writing a ServletTestCase apply to the other types of Cactus TestCases. In order for any Servlet tests to run, you need to map the ServletRedirector in web.xml:

<filter>
 <filter-name>ServletRedirector</filter-name>
 <filter-class> org.apache.cactus.server.ServletTestRedirector
 </filter-class>
</filter>
<filter-mapping>
 <filter-name>ServletRedirector</filter-name>
 <url-pattern>/ServletRedirector</url-pattern>
</filter-mapping>


The Code Under Test

The code under test is a servlet that wraps the behavior of the SessionMapper class as seen in the "Installing Cactus" section in . The following listing contains the code for the MapperServlet. In addition to mapping the results of the request into the session, this servlet prints each request parameter to the response in a separate HTML table cell in the format "key=value". We need Cactus to ensure that the request parameters are appropriately mapped into the session. The MapperServlet also responds to initialization parameters (specifically, it varies the capitalization of its output if the ALL_CAPS parameter is set to "true"). With Cactus, we can set different initialization parameters without having to modify the deployment descriptor for the Web app.

package xptoolkit.cactus;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.io.PrintWriter;
import java.io.IOException;
public class MapperServlet extends HttpServlet{
 public void doGet(HttpServletRequest request,
 HttpServletResponse response)throws IOException{
 Map paramMap = SessionMapper.mapRequestToSession(request);
 PrintWriter writer = response.getWriter();
 writer.println(<TABLE>);
 writer.println(<TR>);
 Set mapEntries = paramMap.entrySet(); for(Iterator iter = mapEntries.iterator(); iter.hasNext();){
 Map.Entry entry = (Map.Entry)iter.next();
 String entryStr = entry.getKey() + "=" + entry.getValue(); if(useAllCaps()){
 entryStr = entryStr.toUpperCase();
 } writer.println("<TD>");
 writer.println(entryStr);
 writer.println("</TD>");
 }
 writer.println("</TR>");
 writer.println("</TABLE>");
 }
 public boolean useAllCaps(){
 String useAllCapsStr =getServletConfig().getInitParameter("ALL_CAPS");
 return useAllCapsStr.equalsIgnoreCase("true");
 }
}


Before the execution of the test proper, Cactus looks for any beginXXX() methods. As you remember from , beginXXX methods are used to set up any request parameters required by the test. Remember that Cactus looks for and executes a beginXXX() method only if it matches with a testXXX() method. In our test we use the beginDoGet() method to add a single parameter "foo" with the value "manchu" to the request:

public void beginDoGet(WebRequest request){
 request.addParameter("foo","manchu");
}


As with JUnit tests, the object under test must be created and initialized manually. We do this in the setUp() method:

public void setUp()throws Exception{
 config.setInitParameter("ALL_CAPS","true");
 servlet = new MapperServlet();
 servlet.init(config);
}


First the "ALL_CAPS" init parameter is set to "true", via the implicit object config, so the test can evaluate the servlet's capitalization handling. An instance of the MapperServlet is then created and initialized with the modified config object. We are now prepared to test that the request parameter "foo" gets correctly mapped into the session:

public void testDoGet() throws Exception{
 servlet.doGet(request, response);
 /*maps the parameters into the session as a side effect*/
 String value = (String)session.getAttribute("foo");
 assertEquals("request param not mapped into session", "manchu", value);
}


First the servlet method doGet() is called with two implicit objects. Then we assert that the session attribute "foo" has the expected value of "manchu". With a ServletTestCase you can also have an optional endXXX() method. In the endDoGet() method, we verify that the output sent to the client is what we expect:

 public void endDoGet(WebResponse response) throws Exception{
 String responseString = response.getText();
 System.out.println(responseString);
 boolean paramInResponse = responseString.indexOf("FOO=MANCHU") > -1;
 assertTrue("param not found in response", paramInResponse);
 }


The getText() method of the Cactus WebResponse returns a String. Then it is searched for the occurrence of the capitalized request parameters. Conversely, we can use HttpUnit to check the response. Cactus, as seen in supports an alternate signature for the endXXX() method using the com.meterware .httpunit.WebResponse:

 public void endDoGet(com.meterware.httpunit.WebResponse response) throws Exception{
 assertEquals("number of tables", 1, response.getTables().length);
 assertEquals("number of rows", 1,
response.getTables()[0].getRowCount()); assertEquals("number of columns", 1, response.getTables()[0].getColumnCount());
 assertEquals("FOO=MANCHU",
response.getTables()[0].getCellAsText(0, 0));
 }


HttpUnit's WebResponse class allows for very fine-grained assertions against a returned HTML page. For more information on HttpUnit, see , “Functional Testing with HttpUnit.” In addition, we test the useAllCaps() method in the servlet:

 public void testUseAllCaps(){
 assertTrue("servlet not set to use all caps",servlet.useAllCaps());
 }


The following listing contains the complete code for MapperServletTest.

package xptoolkit.cactus;
import org.apache.cactus.*;
import junit.framework.*;
public class MapperServletTest extends ServletTestCase{
 private MapperServlet servlet;
 public MapperServletTest(String name) {
 super(name);
 }
 public void setUp()throws Exception{
 config.setInitParameter("ALL_CAPS","true");
 servlet = new MapperServlet();
 servlet.init(config);
 }
 public void beginDoGet(ServletTestRequest request){
 request.addParameter("foo","manchu");
 }
 public void testDoGet() throws Exception{
 servlet.doGet(request, response);
 /*maps the parameters into the session as a side effect*/
 String value = (String)session.getAttribute("foo");
 assertEquals("request param not mapped into session", "manchu", value);
 }
 public void endDoGet(WebResponse response) throws Exception{
 String responseString = response.getText();
 System.out.println(responseString);
 boolean paramInResponse = responseString.indexOf("FOO=MANCHU") > -1;
 assertTrue("param not found in response", paramInResponse);
 }
 public void testUseAllCaps(){
 assertTrue("servlet not set to use all caps",servlet.useAllCaps());
 }
 public void tearDown(){
 /*no significant server-side resources to release*/
 }
 public static TestSuite suite(){
 TestSuite suite = new TestSuite(MapperServletTest.class);
 return suite;
 }
 public static void main(String[] args){
 junit.textui.TestRunner.run(suite());
 }
}


JaVa
   
Comments