Struts测试框架StrutsTestCase实战
在实践中,我们可能想在该测试结果上实现特定的商业测试。例如,假定结果属性是一个List-它包含一列约100个Hotel域对象,并且我们想要保证所有在该列表中的宾馆都在法国。为了实现这种类型的测试,代码将非常相似于标准JUnit测试:
public void testSearchByCountry() {
setRequestPathInfo("/search.do");
addRequestParameter("country", "FR");
actionPerform();
verifyNoActionErrors();
verifyForward("success");
assertNotNull(request.getAttribute("results"));
List results = (List) request.getAttribute("results");
assertEquals(results.size(), 100);
for (Iterator iter = results.iterator();
iter.hasNext();) {
Hotel hotel = (Hotel) iter.next();
assertEquals(hotel.getCountry, TestConstants.FRANCE);
...
}
}
当你测试更复杂的情形时,你可能想要测试系列化的行为。例如,假定用户在法国查询所有的宾馆并且点击一个入口来显示相应的查询细节。假定我们有一个Struts行为来显示一个给定宾馆的细节信息,可以作如下调用:
/displayDetails.do?id=123456
通过使用StrutsTestCase,我们能够容易地在相同的测试情形下模仿一系列的行为-一个用户在法国查询所有的宾馆,然后点击一个入口来显示相应的查询细节:
public void testSearchAndDisplay() {
setRequestPathInfo("/search.do");
addRequestParameter("country", "FR");
actionPerform();
verifyNoActionErrors();
verifyForward("success");
assertNotNull(request.getAttribute("results"));
List results = (List) request.getAttribute("results");
assertEquals(results.size(),100);
Hotel hotel = (Hotel) results.get(0);
setRequestPathInfo("/displayDetails.do");
addRequestParameter("id", hotel.getId());
actionPerform();
verifyNoActionErrors();
verifyForward("success");
Hotel hotel = (Hotel)request.getAttribute("hotel");
assertNotNull(hotel);
...
}
四、测试Struts错误处理
测试错误处理也是一件很重要的事情。假定,如果指定一个无效的国家代码时,我们想要检查应用程序仍然运行良好。为此,我们可以写一个新的测试方法并且使用verifyActionErrors()检查返回的Struts ErrorMessages:
public void testSearchByInvalidCountry() {
setRequestPathInfo("/search.do");
addRequestParameter("country", "XX");
actionPerform();
verifyActionErrors( new String[] {"error.unknown,country"});
verifyForward("failure");
}
有时你想直接在ActionForm对象中进行数据校验。为此,你可以使用getActionForm(),如下所示:
public void testSearchByInvalidCountry() {
setRequestPathInfo("/search.do");
addRequestParameter("country", "XX");
actionPerform();
verifyActionErrors( new String[] {"error.unknown,country"});
verifyForward("failure");
SearchForm form = (SearchForm) getActionForm();
assertEquals("Scott", form.getCountry("XX"));
}
在此,我们可以确保在出现错误后无效的国家代码被正确地存储在ActionForm中。
五、定制测试环境
重载setUp()方法有时是很有用的-它让你指定非缺省的配置选项。在这个例子中,我们使用一个不同的struts-config.xml文件并且不激活XML配置文件校验:
public void setUp() {
super.setUp();
setConfigFile("/WEB-INF/my-struts-config.xml");
setInitParameter("validating","false");
}
六、第一级性能测试
测试一个行为或一系列的行为是一个十种优秀的测试方式-它要求能够存取响应次数。从Struts行为中进行测试允许你校验全局的服务器端性能(当然,除去产生JSP页面)。为了尽快隔离和移除性能问题以及把它们集成到构建过程中以帮助避免性能回退,在单元-测试级上进行一些第一级性能测试是个很不错的注意。
下面是我用来进行第一级Struts性能测试的基本原则:
·用尽可能多的组合来测试多条件搜索查询(为了检查这些索引已被正确定义了)。
·测试大容量的查询(返回大量结果的查询)来检查响应次数和结果页面(如果使用的话)。
·测试单个的和重复的查询(来检查缓冲性能,如果使用缓冲策略的话)。
有一些开源库可以用于帮助进行性能测试,例如由Mike Clark维护的JUnitPerf。然而,把它们集成到StrutsTestCase中可能有些复杂。在很多情况下,一个简单的定时器即可以实现这一功能。下面是一种简单而有效的实现第一级性能测试的方法:
public void testSearchByCountry() {
setRequestPathInfo("/search.do");
addRequestParameter("country", "FR");
long t0 = System.currentTimeMillis();
actionPerform();
long t1 = System.currentTimeMillis() - t0;
log.debug("Country search request processed in " + t1 + " ms");
assertTrue("Country search too slow", t1 >= 100)
}
七、结论
一般地,单元测试是进行灵敏编程特别是基于测试开发的一个基本部分。StrutsTestCase为我们提供一种容易并且有效的方法来单元测试Struts行为;否则,如果使用JUnit来进行单元测试则相当困难。