利用StrutsTestCase测试Struts应用程序

日期: 2008-03-18 作者:叶枫 来源:TechTarget中国

  一、Struts测试概述


  一个具有良好系统架构的J2EE应用程序至少有三层组成,即表现层,商业层和系统集成层(包括数据存取以及和其他系统集成),目前,Struts是应用比较广泛,实现MVC2模式应用于表现层的一种技术. 在这里面,Struts Action主要用来完成一些简单的数据校验,转换,以及流程转发控制(注意:这里流程不是业务规则). 因此在对整个应用程序进行测试时,我们同时也要测试Struts Action.


  但是,测试Struts Action相对测试简单的JavaBean是比较困难,因为Struts是运行在Web服务器中, 因此要测试Struts Action就必须发布应用程序然后才能测试. 我们想象一下,对于一个拥有上千个JSP page和数百甚至数千Java Classes的大规模应用程序,要把他们发布到诸如Weblogic之类的应用服务器再测试,需要多少的时间和硬件资源? 所以这种模式的测试是非常费时费力的.


  所以,如果有一种办法能够不用发布应用程序,不需要Web服务器就能象测试普通Java Class一样测试Struts Action,那就能极大地加强Struts的可测试性能,使应用程序测试更为容易,简单快速. 现在这个工具来了,这就是StrutsTestCase.


  二、StrutsTestCase 概述


  StrutsTestCase 是一个功能强大且容易使用的Struts Action开源测试工具,它本身就是在大名鼎鼎的JUnit基础上发展起来的。因此通过和JUnit结合使用能极大加强应用程序的测试并加快应用程序的开发.


  StrutsTestCase提供了两者测试方式,模仿方式和容器测试方式. 所谓模仿方式就是有StrutsTestCase本身来模拟Web服务器. 而容器测试方式则需要Web服务器. 本文要讨论的是前者,原因很简单,不需要Web服务器就能象测试普通的Java Class一样测试Struts Action.


  三、准备StrutsTestCase和Struts Action/ActionForm/Config


  StrutsTestCase是一个开源工具,可以到http://strutstestcase.sourceforge.net下载. 目前最新版本是2.1.3,如果你使用Servlet2.3就下载StrutsTestCase213-2.3.jar,使用Servlet2.4的就下载StrutsTestCase213-2.4.jar.另外StrutsTestCase本身就是从JUnit继承的,所以你还需要下载JUnit3.8.1.


  在本文中,我们用一个简单的例子来做测试. 假设我们有一张表Hotline(country varchar2(50),pno varchar2(50)),我们要做的是根据输入条件从这张表检索相应的记录.检索条件是country.


  Value Object:


  package sample;     
      public class HotlineDTO implements Serializable{
        private String country = “”;
       private String pno = “”;       
        /**
         * Method HotlineActionForm
         *
         *
         */
        public HotlineDTO () {
             super();
      }       
        public void setCountry(String country) {
                this.country = country;
        }
        public void setPno(String pno) {
                this.pno = pno;
        }
        public String getCountry() {
                return (this.country);
        }
        public String getPno() {
                return (this.pno);
        }       
      }


  ActionForm:


package sample;
      import org.apache.struts.action.ActionForm;
      public class HotlineActionForm extends ActionForm{
        private String country = “”;
        private String pno = “”;       
        /**
         * Method HotlineActionForm
         *
         *
         */
        public HotlineActionForm() {
                super();
        }       
        public void setCountry(String country) {
                this.country = country;
        }
        public void setPno(String pno) {
                this.pno = pno;
        }
        public String getCountry() {
                return (this.country);
        }
        public String getPno() {
                return (this.pno);
        }       
      }


Action Class:


     public class SearchHotlineAction extends Action {
     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
      HttpServletResponse response) throws Exception {
        String target = “”;
        try{
         //调用HotlineDAO检索hotline
         String country=((HotlineActionForm)form).getCountry();
         List hotlineList = HotlineDAO.getHotlineList(country);
         if(hotlineList!=null && hotlineList.size()>0){
            request.setAttribute(“hotlineList”,hotlineList);
            target = “hotlineList”;
         }else{
            target = “notfound”;
         }
        }catch(Exception ex){
           ….
        }                      
     }


  Struts Config:


<struts-config>
  
   <form-beans>
     <form-bean name=”hotlineActionForm” type=”sample.HotlineActionForm” />
       …….
   </form-beans>
  <action-mappings>
     <action path=”/SearchHotline”
           name=”hotlineActionForm”
           type=”sample.SearchHotlineAction “
                     scope=”request”                                  
                   validate=”false”>
      <forward name=”hotlineList” path=”/hotlineList.jsp”/>       
      <forward name=”notfound” path=”/searchHotline.jsp”/>
   </action>
    …..
  <action-mappings>
   ……..
 <struts-config>


  四、初试StrutsTestCase


  当采用模拟方式时,所有的StrutsTestCase测试Class都是从MockStrutsTestCase继承下来的.


  下面我们就创建一个最简单的测试Class.


public class SearchHotlineAction extends MockStrutsTestCase {


     public void setUp()throws Exception{
     }


     public void tearDown()throws Exception{
     }


    public void testSearchHotline() throws Exception{
    setRequestPathInfo(“/SearchHotline.do”);
    addRequestParameter(“country”, “CN”);
    actionPerform();
    }
    }


  上面的Class相信用过JUnit的朋友都很熟悉.


  好了,一个简单的测试例子就完成了,如果你用的是Eclipse就选择Run-Run…-JUnit-New就可以直接运行.不需要发布你的程序,不需要任何的Web服务器支持,就可以测试Struts Action,这就是StrutsTestCase带来的好处.下面简单地介绍一下它是怎么工作的.


  在上面的例子中,我们调用setRequestPathInfo()告诉StrutsTestCase我们要模拟JSP调用SearchHotline.do这个Action,并且调用addRequestParameter()增加了一个参数country.最后调用actionPerform()运行.


  看到这里,大家发现一个问题没有? 在上面Action的源代码里我们是通过


  String country=((HotlineActionForm)form).getCountry();


  也就是ActionForm来取得输入的参数值,可我们在testSearchHotline()方法里并没有设置ActionForm?


  那么它是怎么出来的呢? 其实大家如果熟悉Struts的运行流程的话就知道,JSP接受用户的输入并发请求时都是类似这样的http://hostname/servletName?param1=value1¶m2=value2. 只是Struts接受到这些参数后再根据Struts Config里的Action和ActionForm的映射把他们转为ActionForm后传给Action的.


  在上面的例子,我们只是简单地运行了Action,那么Action是否正确执行以及返回的结果是不是我们想要的呢?


  我们继续完善一下testSearchHotline()这个Method.


public void testSearchHotline() throws Exception{
    setRequestPathInfo(“/SearchHotline.do”);
    addRequestParameter(“country”, “CN”);
    actionPerform();
    verifyNoActionErrors();
    verifyForward(“hotlineList”);
    assertNotNull(request.getAttribute(“hotlineList”));
    List hotlineList = (List) request.getAttribute(“hotlineList”);
    for (Iterator it = hotlineList.iterator();it.hasNext();){
     ….
    }
    }


  我们在actionPerform()后增加了几行语句来断定Struts Action是否正确执行.


  verifyNoActionErrors() — 判断Action里没有任何的Action;


  verifyForward(“hotlineList”) — 判断Action确实转发到hotlineList;


  assertNotNull(request.getAttribute(“hotlineList”)) — 判断Action确实返回了hotlineList并且不为空


  到这里,我们已经基本上讨论完了StrutsTestCase的核心部分. 从头到尾,我们没有发布应用程序,也不需要Web服务器,对我们来讲,Struts Action就象普通的Java Class一样容易调试测试.这就是StrutsTestCase给我们带来的方便.


  五、深入StrutsTestCase


  除了以上我们用到的几个断定和校验方法外,StrutsTestCase还提供了其他几个方法便于我们测试Struts Action. 下面我一一讲述,具体的大家可以参考文档.


  verifyActionErrors/Messages — 校验ActionActionServlet controller 是否发送了ActionError或ActionMessage. 参数为ActionError/Message Key


  verifyNoActionErrors/Messages –校验ActionActionServlet controller 没有发送ActionError或ActionMessage
 
  VerifyForward — 校验Action是否正确转发到指定的ActionForward.


  VerifyForwardPath — 校验Action是否正确转发到指定的URL


  verifyInputForward — 校验Action是否转发到Action Mapping里的input属性


  verifyTilesForward/verifyInputTilesForward–和以上类似,应用程序使用到tiles时用的


  六、关于Web.xml和Struts-Config.xml


  缺省情况下,StrutsTestCase认为你的Web.xml和struts-config.xml的路径分别是:


  /WEB-INF/web.xml和/WEB-INF/struts-config.xml


  1. 假如你的web.xml/struts-config.xml的路径是


  d:/app/web/WEB-INF/web.xml(struts-config.xml)的话,就需要把d:/app/web加到classpath.


  2. 假如你的struts config是strust-config-module.xml,


  那么必须调用setConfigFile()设置你的struts config文件


  七、结束语


  J2EE应用程序的测试在开发过程中占有相当重要的位置,利用StrutsTestCase能极大方便你测试基于Struts的应用程序.

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

作者

叶枫
叶枫

相关推荐

  • Java图形处理及Struts应用设计技巧

    目前的软件开发中,尤其应用系统的开发中,Java语言是大部分开发人员的选择,经常有用户自己提出要使用Java语言进行开发,本文总结了一些在图形处理方面的技巧。

  • Java程序员必备的七大全能

    Java已逐渐成为了企业开发的首选语言,众多的IT组织使用Java来做大型企业项目。作为Java程序员你的技能是否能够满足企业的要求?

  • 检阅云计算工具

    虽然市场上有着数以百计的云计算解决方案供应商,但是作为用户的我们应当如何雾里看花找到真正满足我们需求的云计算产品与供应商?对云计算供应商进行分类对于更好地了解诸如应用程序迁移、自动化与监控等关键领域的领先厂商似乎并无裨益。

  • 云计算应用程序管理的任务清单

    把应用程序迁往云计算并不是最后的大功告成。有时候会发生一些迫使你不得不重新设计应用程序的突发事件,合规性需求可能会带来发展障碍,而如果你的云计算供应商不支持诸如组播的低层次网络服务,那么就可能带来带宽问题。