一Struts测试概述
一个具有良好系统架构的JEE应用程序至少有三层组成即表现层商业层和系统
集成层(包括数据存取以及和其他系统集成)目前Struts是应用比较广泛实现MVC模式应用于表现层的一种技术 在这里面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是一个开源工具可以到下载 目前最新版本是
如果你使用Servlet就下载StrutsTestCasejar使用Servlet的就下载StrutsTestCasejar
另外StrutsTestCase本身就是从JUnit继承的所以你还需要下载JUnit
在本文中我们用一个简单的例子来做测试 假设我们有一张表Hotline(country varchar()pno varchar())
我们要做的是根据输入条件从这张表检索相应的记录检索条件是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) {
untry = country;
}
public void setPno(String pno) {
thispno = pno;
}
public String getCountry() {
return (untry);
}
public String getPno() {
return (thispno);
}
}
ActionForm:
package sample;
import orgapachestrutsactionActionForm;
public class HotlineActionForm extends ActionForm{
private String country = ;
private String pno = ;
/**
* Method HotlineActionForm
*
*
*/
public HotlineActionForm() {
super();
}
public void setCountry(String country) {
untry = country;
}
public void setPno(String pno) {
thispno = pno;
}
public String getCountry() {
return (untry);
}
public String getPno() {
return (thispno);
}
}
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 = HotlineDAOgetHotlineList(country);
if(hotlineList!=null && hotlineListsize()>){
requestsetAttribute(hotlineListhotlineList);
target = hotlineList;
}else{
target = notfound;
}
}catch(Exception ex){
}
}
Struts Config:
<strutsconfig>
<formbeans>
<formbean name=hotlineActionForm type=sampleHotlineActionForm />
</formbeans><actionmappings>
<action path=/SearchHotline
name=hotlineActionForm
type=sampleSearchHotlineAction
scope=request
validate=false>
<forward name=hotlineList path=/hotlineListjsp/>
<forward name=notfound path=/searchHotlinejsp/>
</action>
<actionmappings>
<strutsconfig>
四初试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(/SearchHotlinedo);
addRequestParameter(country CN);
actionPerform();
}
}
上面的Class相信用过JUnit的朋友都很熟悉
好了一个简单的测试例子就完成了如果你用的是Eclipse就选择RunRunJUnitNew就可以直接运行不需要发布你的程序不需要任何的Web服务器支持就可以测试Struts Action这就是StrutsTestCase带来的好处下面简单地介绍一下它是怎么工作的
在上面的例子中我们调用setRequestPathInfo()告诉StrutsTestCase我们要模拟JSP调用SearchHotlinedo这个Action并且调用addRequestParameter()增加了一个参数country最后调用actionPerform()运行
看到这里大家发现一个问题没有? 在上面Action的源代码里我们是通过
String country=((HotlineActionForm)form)getCountry();
也就是ActionForm来取得输入的参数值可我们在testSearchHotline()方法里并没有设置ActionForm?
那么它是怎么出来的呢? 其实大家如果熟悉Struts的运行流程的话就知道JSP接受用户的输入并发请求时都是类似这样//hostname/servletName?param=value¶m=value 只是Struts接受到这些参数后再根据Struts Config里的Action和ActionForm的映射把他们转为ActionForm后传给Action的
在上面的例子我们只是简单地运行了Action那么Action是否正确执行以及返回的结果是不是我们想要的呢?
我们继续完善一下testSearchHotline()这个Method
public void testSearchHotline() throws Exception{
setRequestPathInfo(/SearchHotlinedo);
addRequestParameter(country CN);
actionPerform();
verifyNoActionErrors();
verifyForward(hotlineList);
assertNotNull(requestgetAttribute(hotlineList));
List hotlineList = (List) requestgetAttribute(hotlineList);
for (Iterator it = erator();ithasNext();){
}
}
我们在actionPerform()后增加了几行语句来断定Struts Action是否正确执行
verifyNoActionErrors() 判断Action里没有任何的Action;
verifyForward(hotlineList) 判断Action确实转发到hotlineList;
assertNotNull(requestgetAttribute(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时用的
六关于Webxml和StrutsConfigxml
缺省情况下StrutsTestCase认为你的Webxml和strutsconfigxml的路径分别是:
/WEBINF/webxml和/WEBINF/strutsconfigxml
假如你的webxml/strutsconfigxml的路径是d:/app/web/WEBINF/webxml(strutsconfigxml)的话就需要把d:/app/web加到classpath
假如你的struts config是strustconfigmodulexml那么必须调用setConfigFile()设置你的struts config文件
七结束语
JEE应用程序的测试在开发过程中占有相当重要的位置利用StrutsTestCase能极大方便你测试基于Struts的应用程序