StrutsTestCase 使用的一点感悟


StrutsTestCase用于对基于Struts框架的Web应用进行单元测试,它可以用来测试ActionForm,Action的Execute方法,Action Forward, 及转向后的JSP是否正确。一个典型的Case代码如下:
 
        setRequestPathInfo( " /DriveBus " );
        addRequestParameter(
" driver " " tang " );
        actionPerform();
        verifyForward(
" success " );
       
 
就这样的短短几行代码,在实际运行过程中却遇到很多问题。
 
1 . junit.framework.AssertionFailedError: Error initializing action servlet: Unable to find  / WEB - INF / web.xml.  TestCase  is  running from D:ideeclipse3. 0.1 workspaceztest directory.  Context directory has not been  set .  Try calling setContextDirectory() with a relative or absolute path.   / WEB - INF / web.xml must be found under the context directory, the directory the test  case   is  running from, or  in  the classpath.
 这个错误原因是没有找到web-inf/web.xml所在的目录。一般被测代码和测试的代码不是在一个工程下的。如下图的结构所示:
  
 projects
   
|- myWeb
   
|     |- src
   
|     |- WEB - INF
   
|        |- classes
   
|        |- lib
   
|    
   
|        |  struts - confg.xml
   
|        |  web.xml
   
|    
   
|- test
       
|- src
 
test工程包含所有用来测试myWeb工程的TestCase,这时候就需要覆写MockStrutsTestCase里的setup()方法:
protected   void  setUp()  throws  Exception
    
{
        
// TODO Auto-generated method stub
        super.setUp();
        setContextDirectory(
new File("../myWeb"));
    }

   
例如可以用以下的句子来说明.xml的位置所在。

      
  //  set the context directory to /WebRoot
        
//  to find the /WEB-INF/web.xml
        setContextDirectory( new  File( " WebRoot " ));
        setConfigFile(
" MyFileSystem " " /WEB-INF/struts-config.xml " );

SetContextDirectory()方法保证TestCase能正确找到web.xml和struts-config.xml文件。
 
2。 setRequestPathInfo()用来设置页面的form提交时执行的action,如jsp中form代码为:<FORM action="DriveBus.do" method="post">,则应该写成setRequestPathInfo("/DriveBus").
注意该函数的参数:
   1)DriveBus前面的左斜杠是必需的。
   2)不能包含context路径。
   3)在后面加上.do是没有问题的。
 
3。setRequestPathInfo()存在的问题
   当调用该方法时,会调用Common中的stripActionPath()进行处理,当setRequestPathInfo()的传入参数为“/DriveBus.do”时,会被截成“/DriveBus”,它将会设置到request的pathinfo字段。 问题就在这里。
在StrutsTestCase中,对容器内的request进行了模拟,用HttpServletRequestSimulator代替真正的HttpServletRequest。对于部署在容器里的应用,如下函数的输出分别为:
  request.getPathInfo()     null
    request.getRequestURI()     
/ myWeb / DriveBus. do
    request.getRequestURL()     http:
// localhost:8080/myWeb/DriveBus.do
    request.getServletPath()     / DriveBus. do
  
而模拟的request得出的输出为:
 request.getPathInfo()     / DriveBus
    request.getRequestURI()     
null
    request.getRequestURL()    
null
    request.getServletPath()     
null
   
可 见,HttpServletRequestSimulator并没有能够很好地模拟request,当被测程序中调用了 request.getPathInfo()以外的方法时,测试很可能不会通过(抛NullPointerException异常),或者会出现错误的测 试结果。
 
这个问题我自己就是受害者。
请看如下代码:

ublic  void  testDownloadFileSuccess()  {
        setRequestPathInfo(
"/file");

        HttpServletRequestSimulator requestSimulator 
= new HttpServletRequestSimulator(
                context);

        requestSimulator.setRequestURI(
"/MyFileSystem/do/file");
        requestSimulator
                .setRequestURL(
"http://localhost:8080/MyFileSystem/do/file");
        requestSimulator.setServletPath(
"/do");
        requestSimulator.setContextPath(
"/MyFileSystem");
        requestSimulator.setQueryString(
"fName=/dlf/bootfont.bin");

        addRequestParameter(
"dirmapping""");
        addRequestParameter(
"filebase""c:/");
        addRequestParameter(
"tempDir",
                
"c:/java/tomcat 5.0/webapps/MyFileSystem/");

        actionPerform();
        
        
/*//assertEquals("servletPath","/do");
        assertEquals("folder","folder");
        assertEquals("self","self");
        assertEquals("requestURI","requestURI");
        assertEquals("path","path");
*/


    }

其中被我注释掉的代码是这个测试通过的断言。
这个不知道是我在初始化

  HttpServletRequestSimulator requestSimulator = new HttpServletRequestSimulator(
    context);
时这个context是否错误了。

期待有人来解决一下这个模拟测试的问题。

4。多模块测试
StrutsTestCase支持对多模块的测试,在setRequestPathInfo()中可以指定模块名称,setRequestPathInfo(String moduleName, String pathInfo),其部分代码如下:
   this .actionPath  =  Common.stripActionPath(pathInfo);
        
if  (moduleName  !=   null {
            
if (!moduleName.equals("")) {
                
if (!moduleName.startsWith("/"))
                    moduleName 
= "/" + moduleName;
                
if (!moduleName.endsWith("/"))
                    moduleName 
= moduleName + "/";
            }

            
if (logger.isDebugEnabled()) {
                logger.debug(
"setting request attribute - name = " + Common.INCLUDE_SERVLET_PATH + ", value = " + moduleName);
            }

            
this.request.setAttribute(Common.INCLUDE_SERVLET_PATH, moduleName);
        }

        
this .request.setPathInfo(actionPath);
        
this .requestPathSet  =   true ;
  
它将传入的模块名名设置到request的Common.INCLUDE_SERVLET_PATH属性,但是在verifyForwardPath()的代码中却有这样一段:
String moduleName  =  request.getServletPath()  !=   null   ?  request.getServletPath() :  "" ;
        
if  ((moduleName  ==   null   ||  moduleName.equalsIgnoreCase( "" ))  &&  request.getAttribute(INCLUDE_SERVLET_PATH)  !=   null )
            
//  check to see if this is a MockStrutsTestCase call
            moduleName  =  (String) request.getAttribute(INCLUDE_SERVLET_PATH);
   
  当可以取到ServletPath时,将其值作为moduleName,这个真是让人想不通!!servletPath和模块名有什么关系呢?
 
 (对于URI, URL, URN的详细说明见: http://www.ietf.org/rfc/rfc1738.txt,所以StrutsTestCase对HttpServletRequest的模拟是不符合规范的)
 
5。contextPath
这个值始终是空字符串
 
总 之,当我们使用StrutsTestCase进行测试时,需要对以上问题多加留意,当出错时,可能会是StrutsTestCase本身的问题,必要的 话,可以对其进行源码进行修改,以适合我们系统本身的需求。StrutsTestCase的license是 Apache Software License。
 
附:  Apache Software License (ASL)可以兼容其它任何已知的许可证。 已知的最大例外是GNU Public License (GPL) 和Lesser GNU Public License (LGPL). 重要的是ASL对合作开发相当友好,如果您不想的话,也不会强迫您发布源代码。 Apache Software Foundation名下的德高望众的HTTP服务器用的是相同的许可证。
(完)
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值