JUint学习笔记12---对servlet和filter进行单元测试1

第三部分  testing components

                       从JUnit学习笔记1到11都是讲基本的测试尝试,懂得前面的知识,就可以开始Junit in action的最后一程了---测试组件。

       第三部分让你把在第一第二部分学到的测试知识实践于J2EE组件。我们将重点学习为各种J2EE组件编写单元测试,并能学习如何用Ant、Maven和Eclipse这些工具进行测试。

     第九章 对servlet和filter进行单元测试   Unit-testing servlets and filters

       本章内容

  • 示范测试驱动开发(TDD)方法
  • 用Cactus和mock objects编写servlet和filter的单元测试程序
  • 用Maven运行Cactus测试程序
  • 选择何时用Cactus,何时用mock objects

     介绍管理应用程序

   这个示例管理就是目的是要让管理者对关系数据库进行查询。下图就是典型的web应用框架:

(看不到图片的朋友请点这里)

image

           应用程序首先接受用户包含执行SQL查询的HTTP请求。请求被一个安全filter捕获,该安全filter是用来检查SQL查询是否是一个SELECT查询。如果不是,用户将被定向到一个错误的页面,如果查询是一个SELECT语句,那么就将调用AdminServlet。该servlet执行请求的数据库查询,并将结果传送到JSP显示页面。

用Cactus编写servlet测试

       在这部分的内容中,我们重点是进行AdminServlet部分执行单元测试。在写代码之前就开始写测试程序叫驱动测试开发或测试先行策略。

       先来分析一下AdminServlet的需求,该servlet从Http请求中提取包括将要执行命令的需用参数。然后它将使用提取的命令来获取数据。最后将控制权交给JSP页面来显示穿过来的数据。我们把对应于这些行为的方法分别称为getCommand、executeCommand和callView。

       设计第一个测试

         下面的代码给出了对getCommand方法的测试。

package junitbook.servlets;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.servlet.ServletException;

import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;
import org.apache.commons.beanutils.BasicDynaClass;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;

public class TestAdminServlet extends ServletTestCase
{
    public void beginGetCommandOk(WebRequest request)    ;测试有效的情况
    {                                                    ;定义了command
        request.addParameter("command", "SELECT...");    ;作为Http的参数
    }                                                    ;
                                                         ;
    public void testGetCommandOk() throws Exception      ;
    {                                                    ;
        AdminServlet servlet = new AdminServlet();       ;
        String command = servlet.getCommand(request);    ;
                                                         ;
        assertEquals("SELECT...", command);              ;
    }
    
    public void testGetCommandNotDefined()      ;测试无效的情况,没有定义命令参数
    {
        AdminServlet servlet = new AdminServlet();

        try 
        {
            servlet.getCommand(request);
            fail("Command should not have existed");
        }
        catch (ServletException expected)
        {
            assertTrue(true);
        }        
    }
}

能让TestAdminServlet编译通过的最简单的代码

package junitbook.servlets;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;

public class AdminServlet extends HttpServlet
{   
    public String getCommand(HttpServletRequest request)
        throws ServletException
    {
        return null;
    }
}

在你继续其它测试和实现满足测试的最小应用之前,设法运行Cactus测试。虽然是失败的,但是你至少知道为什么会失败。 然后,当你实现测试中的代码时,测试将会成功!

   -----------------------------------------------------------------------------------------------    
   -JUnit最佳实践  记得检验测试在应当失败的时候失败---------------------------------------------------

使用Maven来运行Cactus测试

     在前面我们已经学习了使用Cactus/Jetty集成,从一个IDE中来进行Cactus测试。这次,我们将学会使用Maven Cactus插件在Tomcat中进行测试。Tomcat是众所周知的servlet/JSP引擎。Maven Cactus插件是运行Cactus测试最容易的方法之一。所有的事物对于使用者来说都是自动和透明的:你的应用文件war文件的“cactus”化、启动你的容器、配置“cactus”化的war,执行Cactus测试,及停止你的容器。(“cactus化”就是自动附加Cactus jars,并且把Cactus需要的入口附加在你的web.xml文件中)。

    默认情况下,Maven Cactus插件在src/testcactus目录下查找Cactus测试程序。我们也需要将所有的元数据和资源文件放在src/webapp目录下。管理应用程序的web.xml文件如下:

1.0" encoding="ISO-8859-1"?>

-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">



  
    AdminServlet
    <servlet-class>junitbook.servlets.AdminServletclass>
  

  
    AdminServlet
    /AdminServlet
  


   要用Maven运行Cactus测试,我们还要提供一个有效的project.xml文件,代码如下,关于细节,在前面的笔记中有描述

1.0" encoding="ISO-8859-1"?>


  3
  junitbook-servlets
  JUnit in Action - Unit-testing servlets and filters
  1.0
  
    Manning Publications Co.
    http://www.manning.com/
    http://www.manning.com/front/dance.gif
  
  2002-2003
  <package>junitbook.servletspackage>
  /images/jia.jpg

  
    Chapter 9 shows how to unit test Servlets annd Filters using 
    both the Mock Object approach and the in-container approach. 
    It highlights how they complement each other and give 
    strategies on when to use them. 
  
  
    Chapter 9 of JUnit in Action: Unit-testing servlets and filters
  

  http://sourceforge.net/projects/junitbook/

  
    
      Vincent Massol
      vmassol
      vmassol@users.sourceforge.net
      Pivolis
      
        Java Developer
      
    
  

  

    
      commons-beanutils
      commons-beanutils
      1.6.1
      
        true
      
    

    
      servletapi
      servletapi
      2.3
    

    
      easymock
      easymock
      1.0
    

    
      mockobjects
      mockobjects-core
      0.09
    

  

  
    src/java
    src/test
    
      
        **/Test*.java
      
      
        **/Test*All.java
      
    
  

  
    maven-cactus-plugin
  

  1. 首先,定义你要运行时需要的jar文件。你不需要包含Cactus相关jar,因为Maven Cactus插件自动包含这些jar。
  2. Maven Cactus插件使用war文件。元素告诉Maven在生产的成品war中包括Commons BeanUtils jars。成品war已被Maven Cactus插件cactus化。注意因为你将会在你的servlet中使用Commons BeanUtils jars,所以必须包含对BeanUtils的依赖关系。
  3. 包含/排除纯粹的JUnit测试以匹配你想运行的测试。
  4. 列出生成的报告。

在运行Cactus插件之前,你要通告Cactus插件,Tomcat被安装在你机器哪个位置,这样才能在能在容器中运行Cactus测试。Cactus插件需要你在你的project.properties文件中增加下面的这一行:

           cactus.home.tomcat4x =C:/Apps/jakarta-tomcat-4.1.24

完成Cactus servlet测试

 使得测试通过的getCommand实现

package junitbook.servlets;

import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AdminServlet extends HttpServlet
{
    public static final String COMMAND_PARAM = "command";
     
    public String getCommand(HttpServletRequest request)
        throws ServletException
    {
        String command = request.getParameter(COMMAND_PARAM);
        if (command == null)
        {
            throw new ServletException("Missing parameter ["
                + COMMAND_PARAM + "]");
        }
        return command;
    }

    public void callView(HttpServletRequest request)
    {
    }
}
测试callView方法
  在TestAdminServlet中添加如下代码:
 private Collection createCommandResult() throws Exception
    {
        List results = new ArrayList();
        
        DynaProperty[] props = new DynaProperty[] {
            new DynaProperty("id", String.class),
            new DynaProperty("responsetime", Long.class)
        };
        BasicDynaClass dynaClass = new BasicDynaClass("requesttime", 
            null, props);

        DynaBean request1 = dynaClass.newInstance();
        request1.set("id", "12345");
        request1.set("responsetime", new Long(500));
        results.add(request1);

        DynaBean request2 = dynaClass.newInstance();
        request1.set("id", "56789");
        request1.set("responsetime", new Long(430));
        results.add(request2);
        
        return results;
    }
         
    public void testCallView() throws Exception
    {
        AdminServlet servlet = new AdminServlet();       

        // Set the result of the exection of the command in the
        // HTTP request so that the JSP page can get the data to
        // display         
        request.setAttribute("result", createCommandResult());

        servlet.callView(request);
    }

    public void beginDoGet(WebRequest request)
    {
        request.addParameter("command", "SELECT...");
    }
使得测试通过的callView方法
          放到AdminServlet.java中
  public void callView(HttpServletRequest request)
    {
    }

    public Collection executeCommand(String command) 
        throws Exception
    {
        throw new RuntimeException("not implemented");
    }
测试doGet方法  
doGet的单元测试
 public void beginDoGet(WebRequest request)
    {
        request.addParameter("command", "SELECT...");
    }

    public void testDoGet() throws Exception
    {
        AdminServlet servlet = new AdminServlet()
        {
            public Collection executeCommand(String command) 
                throws Exception
            {
                return createCommandResult();
            }
        };
              
        servlet.doGet(request, response);

        // Verify that the result of executing the command has been
        // stored in the HTTP request as an attribute that will be
        // passed to the JSP page.
        Collection results = 
            (Collection) request.getAttribute("result");        
        assertNotNull("Failed to get execution results from the "
            + "request", results);               
        assertEquals(2, results.size());
    }

使得测试通过的doGet方法

 public void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException
    {
        try 
        {
            Collection results = 
                executeCommand(getCommand(request));
            request.setAttribute("result", results);        
        }
        catch (Exception e)
        {
            throw new ServletException(
                "Failed to execute command", e);
        }
    }

有两点需要注意,首先,对callView的调用在doGet中没有出现;测试也没有要求。其次executeCommand被调用,将抛出RuntimeException异常,当然你也可以返回null,但是抛出异常是个比较好的做法,如果方法被错误的调用,你也就不会感到任何的惊奇。 

                                                                                                                                 笔记十二是描述使用mock objects测试servlet 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值