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在簽名上不依賴(lài)預(yù)HTTP。當(dāng)訪問(wèn)需要的HTTP是,這些資源在運(yùn)行時(shí)能構(gòu)被注入。Action,servlet資源看上區(qū)就像通用的Maps。當(dāng)在Framework外部測(cè)試時(shí),測(cè)試平臺(tái)會(huì)建立所有需要的任何對(duì)象的映射。
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.
兩個(gè)流行的技術(shù)是獨(dú)立地測(cè)試直接的Action調(diào)用和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.
最簡(jiǎn)單的手段是實(shí)例化Action,調(diào)用相關(guān)的Setter,然后調(diào)用excute。調(diào)用Action直接允許你繞過(guò)復(fù)雜的容器啟動(dòng)過(guò)程。
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的測(cè)試套件,這些測(cè)試套件是復(fù)雜的,并且提供了好的起點(diǎn)。
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.
框架也提供了一個(gè)抽象的StrutsTestCase,支持JUnit3.8,這個(gè)類(lèi)提供了常用的Struts變量和啟動(dòng)代碼。