在我的前一篇文档《测试驱动的开发是重要的》中说过我要写一些测试框架应用方面的文档,我要实现我的诺言之一,这篇文章是介绍StrutsTeseCase的,熟悉并采用struts的开发员曾经一定有过这样一个困扰:我的action如何进行测试?(不是说要“测试先行”么?),如果没有一个可行的测试框架那我的struts环境去哪里模拟(方便的、透明的去模拟)?不要着急,接下来的部分我要向你们介绍这样一种可以满足我们要求的测试框架:strutstestcae。
——写在前面
主要内容介绍:
1. StrutsTeseCase是什么?
2. 它的“家”在哪里?
3. 如何让它来为我们工作?(伴随说明:我到底该实施“测试先行”?)
4. 兼容struts1.1开发员
5. 参考资源
“由于在这里没有牵涉到Struts以及Junit入门的知识,所以我假定这篇文章的读者都是有struts开发经验的开发员并熟悉Junit。”
第一部分:StrutsTestCase是什么?
StrutsTestCase是基于Junit的一个方便测试struts框架的测试框架。它提供模拟对象(Mock Object)和Cactus两种方式来“真实”的运行Struts ActionServlet,它允许你在不启动servlet 引擎的情况下测试你的struts代码。因为strutstestcase可以用ActionServlet来测试你的代码,所以它不光可以测试你的action,同时它也可以测试你的(容器中的?)mapping,frombeans以及forwards声明。我前面曾提到过它对我们开发员来说是“透明的”,因为象action,mapping,form beans 以及forward等等,我们真的可以象在常规的XXXAction中一样在我们的测试代码中随意的使用它们。
在新的版本中它还提供了对tiles和多模块(struts1.1中的功能)的测试。
哇,是不是很奇妙,不要着急,我们很快可以领略到的它的妙处。
第二部分:它的“家”在哪里?
象许许多多的开源项目一样,StrutsTestCase的家也在“sourceforge.org”(我们伟大的sourceforge象一个繁忙的峰槽一样J),你可以通过http://sourceforge.net/project/showfiles.php?group_id=39190来下载它得新版本。
JavaDoc: http://strutstestcase.sourceforge.net/api/index.html
热点论坛:http://sourceforge.net/forum/forum.php?forum_id=121751
常见问题:http://strutstestcase.sourceforge.net/faq.htm
第二部分:如何让它来为我们工作?
“模仿测试(Mock Testing)VS 容器内测试(In-Container Testing)”
通常测试服务器端代码有两种比较常用的测试方法:
模仿对象(mock objects)它通过假设服务器端容器来达到测试效果;
容器内测试(in-container testing),它则是在真实的容器内达到测试效果;
而我们的StrutsTestCase则在对你的测试代码小影响下能分别扮演上边两种角色。因此我们不得不说到它的这两种实现是如何完成的?
StrutsTestCase提供两种基类(他们分别继承标准的Junit TestCase):
MockStrutsTestCase:
通过名字也可以知道他是通过第一中方法在不启动servlet的条件下来模仿一些HttpServlet实现假设容器环境的。
CactusStrutsTestCase:
它是体现在容器内测试(真实环境测试)的,其通过另外一种测试框架(Cactus testing framework:http://jakarta.apache.org/cactus)struts代码。
Ps:本文中牵涉的代码都是通过第一中方法(继承MockStrutsTestCase)来完成测试的,要想用CactusStrutsTeseCase你只要简单的让测试代码继承CactusStrutsTeseCase即可。
下面我们着重讲解MockStrutsTestCase是为我们工作的?
首先我们先看看一个简单的LoginAction的简化代码:
public class LoginAction extends Action {
public ActionForward perform(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
{
String username = ((LoginForm) form).getUsername();
String password = ((LoginForm) form).getPassword();
ActionErrors errors = new ActionErrors();
if ((!username.equals("Jplateau")) || (!password.equals("sandy")))
errors.add("password",new ActionError("error.password.mismatch"));
if (!errors.empty()) {
saveErrors(request,errors);
return mapping.findForward("login");
}
// store authentication info on the session
HttpSession session = request.getSession();
session.setAttribute("authentication", username);
// Forward control to the specified suclearcase/" target="_blank" >ccess URI
return mapping.findForward("success");
}
上边LoginAction完成一个简单的登陆意图,从client搜集登陆数据(用户名和密码),然后做一个验证,如果验证有误返回登陆页;如果登陆成功返回成功页(或业务工作平台)并把用户姓名放入session。
那我们从上边这个简单的程序入手:
首先,我们应该创建一个测试用例TestLoginAction,其基本架子是这样的:
(请记住此时上边LoginAction的代码你还没有写,并且struts_config.xml中的关于LoginAction的actionmapping也是没有的,这些东西我们要经过边测试边写,但一定是先写测试,天啊,什么都还没有我该怎样测试啊,不要急,且看下去,J)
public class TestLoginAction extends MockStrutsTestCase {
public void setUp() { super.setUp(); }
public void tearDown() { super.tearDown(); }
public TestLoginAction(String testName) { super(testName); }
public void testSuccessfulLogin() {}
}