利用httpunit测试servlet

系统 1572 0

传统的Java WEB应用中,核心技术莫过于Servlet类与JSP网页,两者均可以通过HttpUnit程序包完成单元测试。对JSP网页的测试主要集中在判断HTTP服务器返回的内容是否符合要求,并且这种测试只能在WEB容器内进行。对于Servlet类的测试,HttpUnit程序包给出了一个非容器内的测试方案,那就是ServletRunner类的使用。

简单测试

为了测试Servlet类,首先要在ServletRunner中注册Servlet类,例如:

Java代码 复制代码
  1. // 模拟WEB服务器   
  2. ServletRunner sr =  new  ServletRunner();   
  3. sr.registerServlet(  "hello.html" , HelloServlet. class .getName() );  

 

上文注册了一个HelloServlet,当程序发出“hello.html”的HTTP请求时,ServletRunner就会调用HelloServlet类予以响应,如:

Java代码 复制代码
  1. // 模拟HTTP客户端   
  2. ServletUnitClient sc = sr.newClient();   
  3.   
  4. // 创建请求   
  5. WebRequest request   =   
  6.      new  GetMethodWebRequest(  "http://localhost/hello.html"  );   
  7.   
  8. // 返回响应   
  9. WebResponse response = sc.getResponse( request );   
  10.   
  11. // 校验结果   
  12. assertEquals( "text/plain" , response.getContentType());   
  13. assertEquals( "UTF-8" , response.getCharacterSet());   
  14. assertEquals( "中国" , response.getText());  
  

根据上述测试过程,我们的HelloServlet类实现如下:

Java代码 复制代码
  1. import  java.io.IOException;   
  2. import  java.io.PrintWriter;   
  3.   
  4. import  javax.servlet.ServletException;   
  5. import  javax.servlet.http.HttpServlet;   
  6. import  javax.servlet.http.HttpServletRequest;   
  7. import  javax.servlet.http.HttpServletResponse;   
  8.   
  9. public   class  HelloServlet  extends  HttpServlet {   
  10.   
  11.      @Override   
  12.      protected   void  doGet(HttpServletRequest req, HttpServletResponse resp)   
  13.              throws  ServletException, IOException {   
  14.   
  15.         resp.setContentType( "text/plain" );   
  16.         resp.setCharacterEncoding( "UTF-8" );   
  17.   
  18.         PrintWriter pw = resp.getWriter();   
  19.         pw.write( "中国" );   
  20.     }   
  21. }  
  

当然,我们也可以判断Servlet类操作session的过程是否正确,如:

Java代码 复制代码
  1. import  junit.framework.TestCase;   
  2.   
  3. import  com.meterware.httpunit.GetMethodWebRequest;   
  4. import  com.meterware.httpunit.WebRequest;   
  5. import  com.meterware.httpunit.WebResponse;   
  6. import  com.meterware.servletunit.ServletRunner;   
  7. import  com.meterware.servletunit.ServletUnitClient;   
  8.   
  9. public   class  HelloTest  extends  TestCase {   
  10.   
  11.      public   void  testHelloServlet()  throws  Exception {   
  12.           
  13.         ServletRunner sr =  new  ServletRunner();   
  14.         sr.registerServlet( "hello.html" , HelloServlet. class .getName());   
  15.           
  16.         ServletUnitClient sc = sr.newClient();   
  17.           
  18.         WebRequest request   =   
  19.              new  GetMethodWebRequest(  "http://localhost/hello.html"  );   
  20.         WebResponse response = sc.getResponse( request );   
  21.           
  22.          // 判断session中的值   
  23.         assertEquals( "darxin" , sc.getSession( false ).getAttribute( "userId" ));   
  24.           
  25.         assertEquals( "text/plain" , response.getContentType());   
  26.         assertEquals( "UTF-8" , response.getCharacterSet());   
  27.         assertEquals( "中国" , response.getText());          
  28.     }   
  29. }  
  

相应的,我们的Servlet类会做如下改动:

Java代码 复制代码
  1. import  java.io.IOException;   
  2. import  java.io.PrintWriter;   
  3.   
  4. import  javax.servlet.ServletException;   
  5. import  javax.servlet.http.HttpServlet;   
  6. import  javax.servlet.http.HttpServletRequest;   
  7. import  javax.servlet.http.HttpServletResponse;   
  8.   
  9. public   class  HelloServlet  extends  HttpServlet {   
  10.   
  11.      @Override   
  12.      protected   void  doGet(HttpServletRequest req, HttpServletResponse resp)   
  13.              throws  ServletException, IOException {   
  14.   
  15.          // 向session中设置属性   
  16.         req.getSession().setAttribute( "userId" "darxin" );   
  17.           
  18.         resp.setContentType( "text/plain" );   
  19.         resp.setCharacterEncoding( "UTF-8" );   
  20.   
  21.         PrintWriter pw = resp.getWriter();   
  22.         pw.write( "中国" );   
  23.     }   
  24. }  
  

高级应用

上述两例均属于在Servlet类中直接打印响应信息的情况,在实际应用中这种调用已经很少见了。通常我们会利用MVC架构实现Servlet类与JSP网页的功能分离。例如使用Servlet类完成Controller的任务;使用JSP网页完成View的任务。
下图展示了一个典型的利用MVC架构实现HTTP响应的过程:




根据这个图可以看出,第五步会在Servlet类用到转向操作,转向操作的方法如下例:

Java代码 复制代码
  1. // 转向到新的servlet   
  2. request.getRequestDispatcher( "main.html" ).forward(request, response);      
  

 

如何测试具有转向功能的Servlet类呢?首先要明确对于这一类Servlet,我们要测试它们的什么功能:
第一, Servlet类在转向前都保存了哪些数据?保存这些数据的位置在哪儿?
第二, Servlet类是否转向到正确的位置上了?

需要注意的是,通常情况下作为Controller的Servlet类是要转向到作为View的JSP网页的,但是HttpUnit程序包不提供解析JSP网页的方法。为此,我们可以利用stub技术,利用另一个Servlet类为其模拟一个转向目标。
模拟转向目标的任务有两个:
第一, 从数据保存区提取相关的数据;
第二, 将相关的数据以响应的方式向用户端发送。
作为stub的Servlet类不需要进行数据的有效性判断。样例代码如下:

Java代码 复制代码
  1. import  java.io.IOException;   
  2. import  java.io.PrintWriter;   
  3.   
  4. import  javax.servlet.ServletException;   
  5. import  javax.servlet.http.HttpServlet;   
  6. import  javax.servlet.http.HttpServletRequest;   
  7. import  javax.servlet.http.HttpServletResponse;   
  8.   
  9. public   class  MainStub  extends  HttpServlet {   
  10.   
  11.      @Override   
  12.      protected   void  doGet(HttpServletRequest req, HttpServletResponse resp)   
  13.              throws  ServletException, IOException {   
  14.           
  15.      // 从数据保存区提取相关的数据   
  16.         String userId = (String)req.getAttribute( "userId" );   
  17.           
  18.         resp.setContentType( "text/plain" );   
  19.         resp.setCharacterEncoding( "UTF-8" );   
  20.   
  21.          // 将相关的数据以响应的方式向用户端发送   
  22.         PrintWriter pw = resp.getWriter();   
  23.         pw.write(userId);   
  24.     }   
  25. }  
  

相应的,用户端测试代码的任务是:
第一, 注册需要测试的Servlet类与用作stub的Servlet类;
第二, 模拟调用需要测试的Servlet类并为其提供参数;
第三, 检查从用作stub的Servlet类中返回的响应数据是否符合要求。
样例代码如下:

Java代码 复制代码
  1. import  junit.framework.TestCase;   
  2.   
  3. import  com.meterware.httpunit.GetMethodWebRequest;   
  4. import  com.meterware.httpunit.WebRequest;   
  5. import  com.meterware.httpunit.WebResponse;   
  6. import  com.meterware.servletunit.ServletRunner;   
  7. import  com.meterware.servletunit.ServletUnitClient;   
  8.   
  9. public   class  HelloTest  extends  TestCase {   
  10.   
  11.      public   void  testHelloServlet()  throws  Exception {   
  12.   
  13.         ServletRunner sr =  new  ServletRunner();   
  14.          // 注册测试用Servlet          
  15.         sr.registerServlet( "hello.html" , HelloServlet. class .getName());   
  16.          // 注册stub用Servlet          
  17.         sr.registerServlet( "main.html" , MainStub. class .getName());   
  18.           
  19.         ServletUnitClient sc = sr.newClient();   
  20.           
  21.          // 调用测试用Servlet并为其提供参数   
  22.         WebRequest request   =   
  23.              new  GetMethodWebRequest(  "http://localhost/hello.html?userId=darxin"  );   
  24.         WebResponse response = sc.getResponse( request );   
  25.   
  26.          // 检查最终的返回结果          
  27.         assertEquals( "darxin" , response.getText());          
  28.     }   
  29. }  
  

根据测试代码及stub代码,我们最终需要完成的Servlet类代码如下:

Java代码 复制代码
  1. import  java.io.IOException;   
  2. import  javax.servlet.ServletException;   
  3.   
  4. import  javax.servlet.http.HttpServlet;   
  5. import  javax.servlet.http.HttpServletRequest;   
  6. import  javax.servlet.http.HttpServletResponse;   
  7.   
  8. public   class  HelloServlet  extends  HttpServlet {   
  9.   
  10.      @Override   
  11.      protected   void  doGet(HttpServletRequest req, HttpServletResponse resp)   
  12.              throws  ServletException, IOException {   
  13.   
  14.          // 从请求中取出参数   
  15.         String userId = req.getParameter( "userId" );   
  16.   
  17.          // 向request中设置属性   
  18.         req.setAttribute( "userId" , userId);   
  19.   
  20.          // 转向到新的servlet   
  21.         req.getRequestDispatcher( "main.html" ).forward(req, resp);          
  22.     }   
  23. }  
  

 

以上简要说明了如何利用HttpUnit程序包测试Servlet的方法,此方法适用于基本的Servlet实现。
对于容器内测试,建议使用Cactus技术。

 

利用httpunit测试servlet


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论