Spring与Struts结合测试的问题解答

 JDK1.6都出来好长时间了,可我现在公司开发用的还是jdk1.4,说是稳定,另外一个,公司的用户都不愿意花钱升级自己的应用服务器,所以,我们只能在JDK1.4下面开发。另外公司的架构是一个技术牛人写的,采用Struts1.2+spring2.0,前台JSP页面展示采用一套自己的验证,数据传递到后台以及持久层都是那个牛人写的,公用框架没问题,也比较好用,但是缺乏测试。
  我针对持久层写了一些测试,但是对struts的Action层一直没有测试,从网上搜索出来的东西,大都是专门真么SPring或者专门针对Struts的,或者有针对Spring+struts的,但是就一个简单的Demo,对于路径问题,还是没有解决,总是报404或者其他的错误,最终花了好几天的时间,才搞定这个问题,特写博客记录一下,也希望能给有需要这方面东西的朋友提供个帮助。
  其实例子就是简单的一个登录功能,登录成功后进入dwgl模块,包含两个struts的action类,一个在根目录下,一个在dwgl路径下。
web.xml主要配置如下:

<servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>
   org.apache.struts.action.ActionServlet
  </servlet-class>
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/config/struts-config.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/dwgl</param-name>
   <param-value>/WEB-INF/config/struts-config-dwgl.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>

 


其中Spring通过Struts的ContextLoaderPlugIn插件形式加载,项目中有连个Struts的配置文件以及两个spring的配置文件,都存放在WEB-INF/config/目录下面,文件名分别是struts-config.xml、struts-config-dwgl.xml、applicationContext.xml、applicationContext-dwgl.xml。

struts-config.xml内容如下:

<struts-config>
<action-mappings>
 <action input="/login.jsp" path="/login"
  type="org.springframework.web.struts.DelegatingActionProxy">
  <forward name="success" path="/WEB-INF/jsp/success.jsp" />
 </action>
 </action-mappings>
 <message-resources
  parameter="com.accp.web.struts.ApplicationResources" />

   
<!-- 注意,加载Spring插件contextConfigLocation参数必须写成下面的形式,即多个参数之间用逗号隔开,
如果写成applicationContext*.xml的形式,对action层进行测试时候会出现空指针的错误 -->
 <plug-in
  className="org.springframework.web.struts.ContextLoaderPlugIn">
  <set-property property="contextConfigLocation"
   value="/WEB-INF/config/applicationContext.xml,/WEB-INF/config/applicationContext-dwgl.xml" />
 </plug-in>



</struts-config>

 

 struts-config-dwgl.xml内容如下:

<struts-config>
 <action-mappings>
  <action path="/dwgl" parameter="method"
   type="org.springframework.web.struts.DelegatingActionProxy">
   <forward name="success" path="/WEB-INF/jsp/success.jsp" />
  </action>
 </action-mappings>
</struts-config>

  

applicationContext.xml内容如下:

<beans> 
   <bean name="/login" class="com.accp.web.struts.action.LoginAction"/>
</beans>

 

applicationContext-dwgl.xml内容如下:

<beans> 
   <bean name="/dwgl/dwgl" class="com.accp.web.struts.action.dwgl.DwglAction"/>
</beans>

 

 

 

 

具体loginAction内容就是一个简单的提交,

java代码:

public ActionForward execute(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  String userName = request.getParameter("userName");
  ActionMessages errors = new ActionMessages();
  if (userName == null || userName.length() == 0) {
   errors.add("userName", new ActionMessage("errors.userName"));
  }
  if (errors.size() > 0) {
   saveErrors(request, errors);
   return mapping.getInputForward();
  }
  request.setAttribute("userName", userName);
  return mapping.findForward("success");
 }

 

dwglAction继承DispatchAction,内容如下:

public class DwglAction extends DispatchAction {

 public ActionForward querydw(ActionMapping arg0, ActionForm arg1,
   HttpServletRequest arg2, HttpServletResponse arg3) throws Exception {
  return null;
 }
}

 

 

 

 

在这里我只想测试能不能执行到方法内部,所以方法里面也没有什么逻辑处理。

完了写LoginAction的测试,继承自MockStrutsTestCase,但是由于action是Spring进行管理的,所以要写一个将Spring的webapplicationcontext添加到servletcontex中,这里通过SpringWebContextHelper类完成,具体内容为:

public class SpringWebContextHelper {
 private static XmlWebApplicationContext wac = null;
 public static void setWebApplicationContext(ServletContext context) {

  if (context
    .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
   return;
  }
  if(wac == null){
   wac =  new XmlWebApplicationContext();
   wac.setServletContext(context);
   URL classUrl = SpringWebContextHelper.class.getResource("");
   String path = classUrl.getPath();
   try {
    path = URLDecoder.decode(path, "UTF-8");
   } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
   }
   path = path.substring(0 , path.indexOf("WEB-INF")) + "WEB-INF/";
   File configPath = new File(path + "config/");
   String[] applicationContexts = configPath.list(new FilenameFilter(){
    public boolean accept(File dir, String name){
     if(name.toLowerCase().startsWith("applicationcontext")){
      return true;
     }
     return false;
    }    
   });   
   for(int i=0;i<applicationContexts.length;i++){
    applicationContexts[i] = path + "config/" + applicationContexts[i];
   }
   wac.setConfigLocations(applicationContexts);
   wac.refresh();
  }  

  context.setAttribute(
    WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
    wac);
 }

}

 

 

 LoginActionTest 类代码如下:具体注释写的很清楚,大家一看就明白,

 

public class LoginActionTest extends MockStrutsTestCase {

 public void setUp() throws Exception
 {
  super.setUp(); //调用父类的setUp() 
  setContextDirectory(new File("WebRoot")); //指定上下文目录(WEB-INF的父目录)
//  this.setConfigFile("/WEB-INF/config/struts-config.xml,/WEB-INF/config/struts-config-dwgl.xml");
  this.setConfigFile("/WEB-INF/config/struts-config.xml");
  this.setConfigFile("dwgl","/WEB-INF/config/struts-config-dwgl.xml");
  SpringWebContextHelper.setWebApplicationContext(context);
 }
 
 //验证1:在给出正确参数的前提下,是否会返回名为success的ActionForward,以及作用域中是否有正确的数据?
 public void testSuccess()
 {
  //选择要执行哪一个Action
  this.setRequestPathInfo("/login.do");
  //指定请求参数
  this.addRequestParameter("userName", "ACCP");
  //下面这个方法其实就是调用Action中的execute()方法,呵呵。
  this.actionPerform();
  //验证返回是否正确(登录名不为空,应该返回"success")
  this.verifyForward("success");
  //验证“作用域”中的数据是否符合要求
  String expected = "ACCP";
  Object actual = this.getRequest().getAttribute("userName");
  assertEquals(expected, actual);
 }
 
 //验证2:在不给参数的前提下,是否会返回相关的错误消息?
 public void testFailure()
 {
  this.setRequestPathInfo("/login.do");
  this.actionPerform();
  
  this.verifyInputForward();
  
  this.verifyActionErrors(new String[]{ "errors.userName" });
 }
}

 

 

 

由于dwglaction继承自 DispatchAction ,并且在dwgl模块下,所以测试类路径设置以及方法设置要复杂一点,具体代码如下:

public class DwglActionTest extends MockStrutsTestCase {
 public void setUp() throws Exception {
  super.setUp(); // 调用父类的setUp()
  setContextDirectory(new File("WebRoot/")); // 指定上下文目录(WEB-INF的父目录)
  String configfilePath = "/WEB-INF/config/struts-config.xml";
  this.setConfigFile(configfilePath);
  //第一个参数子项目的配置文件,不能以"/"开头
  this.setConfigFile("dwgl","/WEB-INF/config/struts-config-dwgl.xml");
  SpringWebContextHelper.setWebApplicationContext(context);
  setInitParameter("validating","false");
 }
 public void testGetMessage() {
  // 选择要执行哪一个Action,其中第一个参数用来标识子项目,切记必须以“/”开头
  this.setRequestPathInfo("/dwgl","/dwgl.do");
  this.addRequestParameter("method", "querydw");
  this.actionPerform();
 }
 public static void main(String[] args){
  }
}

 

 

 

 

现在写完这些测试方法,感觉好简单,可当时却折磨得我好苦,花了好几天的时间才完成这些测试,当时由于一个路径设置的问题,junit的进度条就是不能变绿,等到最后完成这些测试、进度条变绿,我才舒了一口气,希望对需要的朋友有一些帮助。

附件为所有的源代码,不过由于lib文件太大,我没有进行上传,具体需要以下jar包,log4j、struts、spring、strutstest。

你可能感兴趣的:(spring,xml,Web,struts,servlet)