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服务器用的是相同的许可证。
(完)
|
StrutsTestCase 使用的一点感悟
最新推荐文章于 2014-11-19 22:26:54 发布