Java单元测试Junit(四)使用Cactus测试Servlet

什么是Cactus? 
      Cactus是Apache下的一个开源测试Web层的框架,可以完成模拟J2EE的容器来进行测试,可以测试Servlet,JSP,Filter,EJB等等,以下图片为Cactus官方网站的原理图 
                                    Java单元测试Junit(四)使用Cactus测试Servlet_第1张图片 
当测试DAO时我们可以使用DBUnit来进行对数据库的隔离,当我们测试Service的时候可以使用EasyMock来模拟DAO的实现进行Service和DAO的隔离,虽然我们测试Servlet的时候也可以使用EasyMock来对Session,Request等来进行模拟,但实际上我们会发现,使用Mock来模拟Servlet只能测试简单的Servlet,例如Session,Request,Parameter等,对一些Servlet的返回值,返回了什么View等,测试起来还是力不从心,使用Cactus可以产生模拟的容器来对Servlet进行测试,大大减低了测试难度和提高了测试效率
 

 
  
  1. <dependency> 
  2.     <groupId>httpunitgroupId> 
  3.     <artifactId>httpunitartifactId> 
  4.     <version>1.7version> 
  5. dependency> 
  6. <dependency> 
  7.     <groupId>org.apache.cactusgroupId> 
  8.     <artifactId>cactus.core.framework.uberjar.javaEE.15artifactId> 
  9.     <version>1.8.1version> 
  10. dependency> 



      在maven管理下的src/test/resources/中增加cactus.properties 

 

 
  
  1. cactus.contextURL=http://localhost:8080/test 



      以下为被测试的Servlet 

 

 
  
  1. package com.accentrix.ray.test.unit;  
  2.  
  3. import java.io.IOException;  
  4.  
  5. import javax.servlet.ServletException;  
  6. import javax.servlet.http.HttpServlet;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.  
  10. import com.accentrix.ray.entity.User;  
  11.  
  12. public class LoginServlet extends HttpServlet {  
  13.  
  14.     /**  
  15.      *   
  16.      */ 
  17.     private static final long serialVersionUID = 6916692964267082204L;  
  18.  
  19.     @Override 
  20.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  21.             throws ServletException, IOException {  
  22.         String userName = req.getParameter("username");  
  23.         if (userName == null || "".equals(userName.trim()))  
  24.             resp.sendRedirect("/error.jsp");  
  25.         else 
  26.             req.getRequestDispatcher("/success.jsp").forward(req, resp);  
  27.     }  
  28. }  
  29.  
以下为测试类 

 

 
  
  1. package com.accentrix.ray.test.unit;  
  2.  
  3. import java.io.IOException;  
  4.  
  5. import javax.servlet.ServletException;  
  6.  
  7. import org.apache.cactus.ServletTestCase;  
  8. import org.apache.cactus.WebRequest;  
  9. import org.xml.sax.SAXException;  
  10.  
  11. import com.meterware.httpunit.WebResponse;  
  12.  
  13. public class TestLoginServlet extends ServletTestCase {  
  14.  
  15.     private LoginServlet loginServlet;  
  16.  
  17.     /*  
  18.      * 由begin开始的方法,都被视为客户端方法,这里的操作 都应该是从  
  19.      * 客户端发出的,例如客户端传递给服务端的参数就应该从begin方法  
  20.      * 中传入,参数WebRequest为生成request而需要  
  21.      */ 
  22.     public void beginLogin(WebRequest request) {  
  23.         // 通过request.addParameter()来添加parameter  
  24.         request.addParameter("username""Ray");  
  25.     }  
  26.  
  27.     /*  
  28.      * 初始化对象  
  29.      */ 
  30.     public void setUp() {  
  31.         loginServlet = new LoginServlet();  
  32.     }  
  33.  
  34.     /*  
  35.      * 测试doGet方法  
  36.      */ 
  37.     public void testDoGet() throws ServletException, IOException {  
  38.         // 注意,此时request和response为ServletTestCase的属性  
  39.         loginServlet.doGet(super.request, super.response);  
  40.     }  
  41.  
  42.     /*  
  43.      * 由end开始的方法,都被视为服务器响应方法,这里操作  
  44.      * 的应该是验证服务器传回来的结果,例如返回的JSP是否正确  
  45.      * ,参数WebResponse为验证提供了大量的方法,例如getTable  
  46.      */ 
  47.     public void endDoGet(WebResponse response) throws SAXException {  
  48.         //返回已编译后的html页面的title  
  49.         assertEquals("test", response.getTitle());  
  50.         //返回整个html的document  
  51.         assertEquals("test", response.getDOM().getElementById("Ray").getNodeValue());  
  52.         //返回指定名称的元素  
  53.         assertEquals(3, response.getElementsByTagName("input").length);  
  54.     }  
  55. }  
  56.  



      编写完毕后,还需要把项目布置到服务器当中,开启服务器后运行test case 

注意事项: 
      1.在cactus.properties文件中,contextURL的值需要注意后面不能添加 '/', 
        例如http://localhost:8080/test/ <--这样是错误的,因为Cactus会寻找 
        http://localhost:8080/test/ServletRedirector来解释测试类 

      2.Cactus1.8.1版本目前还不支持Junit4的Annotation,所以开发这需要遵循 
        Junit3.8的规范来开发,例如@Before需要用setUp()来替换 

      3.编写test case时,beginXXX testXXX endXXX为一个组合,xxx为自定义名字, 
        不同组合的begin和end不会互相影响 

      4.在上述例子中endDoGet(WebResponse response)中WebResponse中的类型 
        为httpunit中的实现类com.meterware.httpunit.WebResponse,若开发者 
        使用的是Cactus中的org.apache.cactus.WebRequest时,将不能使用getTable(), 
        getTitle等方法 

      Cactus是功能非常强大的Web容器测试框架,除了测试Servlet还可以测试JSP,Filter,EJB等,当有实际需求时,可以上Cactus官方网站进行学习,上面都有非常详细的Demo和解释http://jakarta.apache.org/cactus/ 


笔者在学习Cactus时发现可以使用Jetty嵌入式服务器达到在测试前启动服务器的效果,但学习过后Demo并不能成功运行,所以请有兴趣的读者参考其他资料,笔者觉得在实际开发当中没有使用Cactus的必要,因为Web层是离前台最近的地方,通过界面点击进行参数等的观察都非常方便,测试的价值并没有Service和DAO的大,而且Cactus虽然功能强大,但易用性并不是太好.建议读者遇到实际需求时认真选择是否使用Cactus

你可能感兴趣的:(Test)