“action is injected by Spring and requires the interceptor stack to be involved as well”,就需要一个“helper factory”去创建Action 和它对应的ActionProxy对象,并能够通过读取struts.xml文件注入对应的interceptors.
要做到这一点,就要做到下面三步骤:
- Specify request parameters which are translated and mapped to the actions domain objects (id in the TestAction class) and then execute the action while also executing all configured interceptors.
- Instead of specifying request parameters, directly specify the values of the domain objects and then execute the action while also executing all configured interceptors.
- Finally, you just might want to execute the action and not worry about executing the interceptors. Here you’ll specify the values of the actions domain objects and then execute the action.
写一个BaseStrutsTest类,实现上面的要求
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import junit.framework.TestCase;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.views.JspSupportServlet;
import org.springframework.context.ApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletConfig;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.ContextLoader;
import java.util.HashMap;
/**
* @author Zarar Siddiqi
*/
public abstract class BaseStrutsTestCase extends TestCase {
private static final String CONFIG_LOCATIONS = "applicationContext-app.xml";
private static ApplicationContext applicationContext;
private Dispatcher dispatcher;
protected ActionProxy proxy;
protected static MockServletContext servletContext;
protected static MockServletConfig servletConfig;
protected MockHttpServletRequest request;
protected MockHttpServletResponse response;
/**
* Created action class based on namespace and name
*
* @param clazz Class for which to create Action
* @param namespace Namespace of action
* @param name Action name
* @return Action class
* @throws Exception Catch-all exception
*/
@SuppressWarnings("unchecked")
protected <T> T createAction(Class<T> clazz, String namespace, String name)
throws Exception {
// create a proxy class which is just a wrapper around the action call.
// The proxy is created by checking the namespace and name against the
// struts.xml configuration
proxy = dispatcher.getContainer().getInstance(ActionProxyFactory.class).
createActionProxy(namespace, name, null, true, false);
// by default, don't pass in any request parameters
proxy.getInvocation().getInvocationContext().setParameters(new HashMap());
// do not execute the result after executing the action
proxy.setExecuteResult(true);
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
// set the actions context to the one which the proxy is using
ServletActionContext.setContext(proxy.getInvocation().getInvocationContext());
ServletActionContext.setRequest(request);
ServletActionContext.setResponse(response);
ServletActionContext.setServletContext(servletContext);
return (T) proxy.getAction();
}
protected void setUp() throws Exception {
if (applicationContext == null) {
// this is the first time so initialize Spring context
servletContext = new MockServletContext();
servletContext.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
CONFIG_LOCATIONS);
applicationContext = (new ContextLoader()).initWebApplicationContext(servletContext);
// Struts JSP support servlet (for Freemarker)
new JspSupportServlet().init(new MockServletConfig(servletContext));
}
// Dispatcher is the guy that actually handles all requests. Pass in
// an empty. Map as the parameters but if you want to change stuff like
// what config files to read, you need to specify them here. Here's how to
// scan packages for actions (thanks to Hardy Ferentschik - Comment 66)
// (see Dispatcher's source code)
HashMap params = new HashMap();
params.put("actionPackages", "com.test.action");
dispatcher = new Dispatcher(servletContext, params);
dispatcher.init();
Dispatcher.setInstance(dispatcher);
}
}
现在就可以test Action类
public class TestTest extends BaseStrutsTestCase{
@Test
public void testExecute() throws Exception {
TestAction test = createAction(TestAction.class, "/", "test"); //action
test.setId("2");
Assert.assertEquals("success" , proxy.execute());
}
}
原来的TestAction类
public class TestAction {
private String id;
public String execute() {
return "success" ;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
resource下的两个配置文件
applicationContext-app.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- <bean id="testAction" class="com.test.action.TestAction" scope="prototype">
</bean>-->
</beans>
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" extends="struts-default" namespace="/">
<action name="test" class="com.test.action.TestAction">
<result name="success">index.jsp</result>
</action>
</package>
</struts>
最后是Maven的pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>tutorial</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>tutorial Maven Webapp</name>
<properties>
<!-- 主要依赖库的版本定义 -->
<spring.version>3.0.4.RELEASE</spring.version>
<hibernate.version>3.5.5-Final</hibernate.version>
<struts2.version>2.2.1</struts2.version>
<jetty.version>6.1.25</jetty.version>
<slf4j.version>1.6.1</slf4j.version>
<selenium.version>2.0a5</selenium.version>
<!-- Plugin的属性定义 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- spring begin -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.9</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<!-- spring end -->
<!-- spring orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- web begin -->
<!-- struts2 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts2.version}</version>
<exclusions>
<exclusion>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
<!--<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-tiles-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.16</version>
</dependency>
<!-- web end -->
<!-- logging -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<!-- test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- j2ee web spec -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.8.0.GA</version>
</dependency>
</dependencies>
<build>
<finalName>tutorial</finalName>
<plugins>
<!-- compiler插件, 设定JDK版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
<!--
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
</plugin>
-->
</plugins>
</build>
</project>
运行命令
mvn test 就行