对Struts2进行单元测试,以struts 2.2.1.1为例 ,可以使用struts2发行包中的struts2-junit-plugin-2.2.1.1.jar,它里面提供了两个类StrutsTestCase、StrutsSpringTestCase,分别提供对纯struts应用和struts+spring整合时的单元测试支持。下面分别说明。

 

1.StrutsTestCase

   首先准备一个纯struts2工程,建立工程过程略,但有如下的类:

   Account.java,是bean

  


  1. package
  2.   
  3. public class
  4. private
  5. private
  6.   
  7. public
  8.     }  
  9.   
  10. public
  11. this.userName = userName;  
  12. this.password = password;  
  13.     }  
  14.   
  15. public
  16. return
  17.     }  
  18.   
  19. public void
  20. this.userName = userName;  
  21.     }  
  22.   
  23. public
  24. return
  25.     }  
  26.   
  27. public void
  28. this.password = password;  
  29.     }  
  30. }  


   AccountAction.java

  


  1. package
  2.   
  3. import
  4. import
  5.   
  6. import
  7.   
  8. public class AccountAction extends
  9.   
  10. private
  11. public String execute() throws
  12. return
  13.     }  
  14.   
  15. public void
  16. if (accountBean.getUserName().length()==0){  
  17. "accountBean.userName","User name is required.");  
  18.         }  
  19.   
  20. if (accountBean.getUserName().length()<5){  
  21. "accountBean.userName","User name must be at least 5 characters long.");  
  22.         }  
  23.   
  24. if (accountBean.getUserName().length()>10){  
  25. "accountBean.userName","User name cannot be at more thant 10 characters long.");  
  26.         }  
  27.     }  
  28.   
  29. public
  30. return
  31.     }  
  32.   
  33. public void
  34. this.accountBean = accountBean;  
  35.     }  
  36. }  


   测试类:

  TestAccountAction.java

   


  1. package
  2.   
  3. import
  4. import
  5. import
  6. import
  7.   
  8. import static
  9.   
  10.   
  11. public class TestAccountAction extends
  12. private
  13. private
  14.   
  15. private void
  16. "/createaccount"); //action url,可以写扩展名".action"也可以干脆不写
  17.         action = (AccountAction) proxy.getAction();  
  18.     }  
  19.   
  20. public void testUserNameErrorMessage() throws
  21. "accountBean.userName", "Bruc");  
  22. "accountBean.password", "test");  
  23.   
  24.         init();  
  25.         proxy.execute();  
  26.   
  27. "Problem There were no errors present in fieldErrors but there should have been one error present",  
  28. 1);  
  29. "Problem field account.userName not present in fieldErrors but it should have been",  
  30. "accountBean.userName"));  
  31.     }  
  32.   
  33. public void testUserNameCorrect() throws
  34. "accountBean.userName", "Bruce");  
  35. "accountBean.password", "test");  
  36.   
  37.         init();  
  38.         String result=proxy.execute();  
  39.   
  40. "Problem There were errors present in fieldErrors but there should not have been any errors present",  
  41. 0);  
  42.   
  43. "Result returned form executing the action was not success but it should have been.",  
  44. "success", result);  
  45.   
  46.     }  
  47. }  

 

   测试逻辑比较简单,action中的validate方法会保证用户名长度在5--9之间。

   定义struts.xml,放在类路径的根目录下,而非web-inf/classes下,否则会找不到,不会加载你定义的内容。


  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <!DOCTYPE struts PUBLIC  
  4. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  5. "http://struts.apache.org/dtds/struts-2.0.dtd">  
  6. <struts>  
  7. package name="testit" namespace="/" extends="struts-default">  
  8. "createaccount" class="action.AccountAction">  
  9. "success">/index.jsp</result>  
  10. "input">/createaccount.jsp</result>  
  11.         </action>  
  12. package>  
  13. </struts>  


   至于action/result的定义中用到的jsp页面,不必真实存在,保持不为空就行,否则,action测试的时候,会说result未定义之类的错误,因为此测试会模拟action真实状态下的运行。运行,一切OK。

   正因为会模拟真实状态下的运行,所以拦截器也会正常被触发,下面再定义一个拦截器测试一下:

   MyInterceptor.java


  1. package
  2.   
  3. import
  4. import
  5.   
  6. public class MyInterceptor extends
  7.   
  8. public String intercept(ActionInvocation actionInvocation) throws
  9. "before processing");  
  10.        String rst= actionInvocation.invoke();  
  11. "bye bye "+actionInvocation.getProxy().getMethod());  
  12. return
  13.     }  
  14. }  


  

   修改一下struts.xml,加入拦截器的定义:

   <package name="testit" namespace="/" extends="struts-default">
        <interceptors>
            <interceptor name="testInterceptor" class="interceptor.MyInterceptor"/>
        </interceptors>
        <action name="createaccount" class="action.AccountAction">
            <result name="success">/index.jsp</result>
            <result name="input">/createaccount.jsp</result>
            <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="testInterceptor"/>
        </action>
    </package>

   运行,控制台会输出:

before processing

   bye bye execute

 

    使用的jar包如下图:

  

尤其是以plugin.jar结尾的文件,更不要加struts2-spring-plugin-2.2.1.1.jar,加了会加载相关的东西,但这里却提供不了,导致测试无法运行。实际spring-beans-2.5.6.jar和spring-context-2.5.6.jar也不是必须的,但加了也无所谓,在StrutsSpringTestCase是需要的。另外,web.xml不需要配置,根本不会去这里找配置信息。

  

2.StrutsSpringTestCase

  这个和前面的过程类似,需要的类分别如下。

  MathAction.java


  1. package
  2.   
  3. import
  4. import
  5. import
  6. import
  7.   
  8. public class MathAction extends
  9. private
  10.   
  11. public String execute() throws
  12. "add.result",service.add(1,2));  
  13. return
  14.     }  
  15.   
  16. public
  17. return
  18.     }  
  19.   
  20. public void
  21. this.service = service;  
  22.     }  
  23. }  


  MathService.java


  1. package
  2.   
  3. public class
  4. public int add(int a,int
  5. return
  6.     }  
  7. }  


  测试类TestMathAction,测试一下MathService.add是否能正确地返回两个数相加的值。

 


  1. import
  2. import
  3. import
  4.   
  5. public class TestMathAction  extends
  6. private
  7. private
  8.   
  9. protected
  10. return "spring/applicationContext.xml";  
  11.     }  
  12.   
  13. private void
  14. "/add");  
  15.         action=(MathAction)proxy.getAction();  
  16.     }  
  17. public void testAdd() throws
  18.         init();  
  19.         proxy.execute();  
  20. "add.result"),3);  
  21.     }  
  22. }  


 

jsp-api.jar和servlet-api.jar,去tomcat里copy一份即可,junit.jar也是需要的(废话?!)