转载

基于 Junit2.0 StrutsTestCase 应用

 

       在我的前一篇文档《测试驱动的开发是重要的》中说过我要写一些测试框架应用方面的文档,今天我要实现我的诺言之一,这篇文章是介绍 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 success 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() {}

}

 

首先我们头脑总中有这样一个 actionmapping( 注意只是假设的 )

 

<action path=”/longin” type=”Jplateau.strutstestcase.LonginAction”

                   scope="request"

                   name="userForm">

<forward  name="success" path="/main.jsp"/>

<forward  name="login" path="/login.jsp"/>

</action>

 

有了这样一个假设,我们就可以从测试代码入手:

public class TestLoginAction extends MockStrutsTestCase {

 

public void setUp() {

 super.setUp();

 // 这里做一些初始化的东西,譬如数据库连接等

 }

 

public void tearDown() {

 super.tearDown();

 // 这里关闭你在 setup 中开启的资源,如关闭数据库连接等

}

 

    public TestLoginAction(String testName) { super(testName); }

 

public void testSuccessfulLogin() {

 

// 选择你要执行哪一个 actionmapping? 这里就用我们刚才做的假设材料

this. setRequestPathInfo("/login");

 

// 首先要初始化提交数据:用户名、密码

this.addRequestParameter(“usrename”,”Jplateau”);

this.addRequestParameter(“passwd”,”sandy”);

// 注意有了这个之后,你就可以从 formbean 中使用提交以后的用户名和密码数据了,下 // 面我会解释

 

// 好,初始化数据完成以后开始执行 action 中的 execute(), 很简单,掉用 actionPerform()

this. ActionPerform();

 

// 严正返回是否正确?这里就用我们刚才做的假设材料

this verifyForward(“success”); .

 

// 下面验证登陆成功以后 session 中是否有用户的名称?

String expect_username_from_session=”Jplateau”;

// 这里需要插写内容,就是 strutstestcase 完全可以在测试代码中使用跟真实 action

// 中一样的环境,譬如可以通过 this.getActionForm() 得到相应的 ActionForm

// 可以通过 this.getRequest() 得到 HttpRequest

// 可以通过 this.getSession() 得到 HttpSession, 如下:

String actual_username_from_session=this.getSession().getAttribute(“authentication”);

 

this . assertEquals(“”, expect_username_from_session, actual_username_from_session);

}

 

public void testFailureLogin(){

// 登陆失败的测试在此就不写了

 

}

}

 

 

上边是一个简单的测试代码,好,运行!他此时肯定是通不过的,首先我们的 java 代码还没有写, struts-config.xml 还没有配,那么,现在你可以现在做这些事情:“用最简单的做法或代码让上边那个测试通过。

 

第三部分:兼容 struts1.1 开发员

 

下面说写和 struts1.1 相关的内容:测试 tiles 和多模块!

 

测试 tiles

假设我们的 actionmapping 中有这样 forward tiles 的情况,如下:

 

// 这里有关 struts tiles 的使用不做介绍,请参考相关资料

<forwardname="success"                     path="/userListLayout"/>

 

同时 tiles_defs.xml 中有相应配置:

 

// 其中 mainLayout 是我在 tiles 定义的类型框架   

<definition name="userListLayout" extends="mainLayout">

      <put name="body" value="/main.jsp" />

  </definition>

 

 

那么我们在测试代码中可以如下测试 tiles

//

this. verifyTilesForward(“success”,”userListLayout”);

 

测试多模块:

 

关于多模块的测试我希望能在下面代码的注释部分给你一个大概的介绍:

 

public class TestLoginAction extends MockStrutsTestCase {

 

    public TestLoginAction(String testName) { super(testName); }

 

public void testSuccessfulLogin() {

   // mymodule ”为系统中某个单独模块的名称(文件夹的名称)

setConfigFile("mymodule","/WEB-INF/struts-config-mymodule.xml");

 

// 这个地方和前面单模块的例子有些差别,此处有两个参数,第一个参数是模块的

// 名称,第二个参数的意义和上边相同;

// 和单模块相比,就上边两处区别

       this.setRequestPathInfo("/mymodule","/login.do");

       this.addRequestParameter("username","Jplateau");

       this.addRequestParameter("password","sandy");

       this.actionPerform();

       this.verifyForward("success");

 

String expect_username_from_session=”Jplateau”;

 

String actual_username_from_session=this.getSession().getAttribute(“authentication”);

 

this . assertEquals(“”, expect_username_from_session, actual_username_from_session);

    }

}

 

 

参考资源:

1.   http://strutstestcase.sourceforge.net

(本篇文章基本上是沿用该篇文档的思路,英文好的可以阅读这篇文档。)

2.   Kent Beck Test-Driven Development By Example

3. 本文首发于本人资料站点:http://plateau.sicool.com/

 

Jplateau 2003 11 12 日星期三 写于广州精博

posted on 2005-08-22 17:43 扭转乾坤 阅读(153) 评论(0)  编辑  收藏 所属分类: Struts相关


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(2)

随笔分类(31)

随笔档案(30)

文章分类(32)

文章档案(33)

相册

PHP小站-首页

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜