The
Struts 2 Action doesn't expose HTTP in its signature. When access to
HTTP resources is needed, references to these resources can be injected
at runtime, but, to the Action, the servlet resources appear as
ordinary Maps. When running tests outside of the framework, the test
scaffolding can create and set a Map with whatever objects are needed
by the test.
Struts2 Action在签名上不依赖预HTTP。当访问需要的HTTP是,这些资源在运行时能构被注入。Action,servlet资源看上区就像通用的Maps。当在Framework外部测试时,测试平台会建立所有需要的任何对象的映射。
There are several approaches to unit testing Struts 2-based applications, whether using JUnit or TestNG.
Two popular techniques are direct Action invocation and testing
interceptors and result-types independently. We will demonstrate both
approaches using JUnit 3.
两个流行的技术是独立地测试直接的Action调用和interceptor和Result-Type。
Direct Action Invocation
The simplest approach is to instantiate your Actions, call the appropriate setters, then invoke execute. Calling the Action directly allows you to bypass all the complicated container setup.
最简单的手段是实例化Action,调用相关的Setter,然后调用excute。调用Action直接允许你绕过复杂的容器启动过程。
package org.petsoar.actions.inventory;
import com.mockobjects.constraint.IsEqual;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork.Action;
import junit.framework.TestCase;
import org.petsoar.pets.Pet;
import org.petsoar.pets.PetStore;
public class TestViewPet extends TestCase {
private Mock mockPetStore;
private ViewPet action;
protected void setUp() throws Exception {
mockPetStore = new Mock(PetStore.class);
PetStore petStore = (PetStore) mockPetStore.proxy();
action = new ViewPet();
action.setPetStore(petStore);
}
public void testViewPet() throws Exception {
Pet existingPet = new Pet();
existingPet.setName("harry");
existingPet.setId(1);
Pet expectedPet = new Pet();
expectedPet.setName("harry");
expectedPet.setId(1);
mockPetStore.expectAndReturn("getPet", C.args(new IsEqual(new Long(1))), existingPet);
action.setId(1);
String result = action.execute();
assertEquals(Action.SUCCESS, result);
assertEquals(expectedPet, existingPet);
mockPetStore.verify();
}
public void testViewPetNoId() throws Exception {
mockPetStore.expectAndReturn("getPet", C.ANY_ARGS, null);
String result = action.execute();
assertEquals(Action.ERROR, result);
assertEquals(1, action.getActionErrors().size());
assertEquals("Invalid pet selected.", action.getActionErrors().iterator().next());
assertNull(action.getPet());
mockPetStore.verify();
}
public void testViewPetInvalidId() throws Exception {
action.setId(-1);
testViewPetNoId();
}
}
Testing Interceptors and/or Result Types
Check out the test suites in XWork and Struts 2. These suites are
comprehensive and provide a good starting point. Here's an example.
取出XWork和Struts2的测试套件,这些测试套件是复杂的,并且提供了好的起点。
public void testDoesNotAllowMethodInvocations() {
Map params = new HashMap();
params.put("@java.lang.System@exit(1).dummy", "dumb value");
HashMap extraContext = new HashMap();
extraContext.put(ActionContext.PARAMETERS, params);
try {
ActionProxy proxy = ActionProxyFactory.getFactory().
createActionProxy("", MockConfigurationProvider.MODEL_DRIVEN_PARAM_TEST, extraContext);
assertEquals(Action.SUCCESS, proxy.execute());
ModelDrivenAction action = (ModelDrivenAction) proxy.getAction();
TestBean model = (TestBean) action.getModel();
String property = System.getProperty("action.security.test");
assertNull(property);
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
The framework also provides built-in support for JUnit 3.8 via an
abstract StrutsTestCase, which provides common Struts variables and
setup code.
框架也提供了一个抽象的StrutsTestCase,支持JUnit3.8,这个类提供了常用的Struts变量和启动代码。