继承DispatchAction的JUnit测试遇初始化异常及空指针问题求助
问题分析
从堆栈信息可直接定位根源:DispatchAction的静态初始化块调用MessageResources.getMessageResources()时返回null,触发NullPointerException,进而引发ExceptionInInitializerError。本质是JUnit测试环境未启动Struts容器,Struts核心资源(如消息资源)未初始化,导致静态代码执行失败。
解决方案
以下是按推荐优先级排序的可行方案:
1. 重构代码:分离业务逻辑与Struts依赖
最彻底的解决方式是将ClassA中的业务逻辑抽离到独立的普通类中,让ClassA仅负责Struts请求调度工作。测试业务逻辑时无需依赖Struts容器。
重构后代码示例
// 独立业务类,无Struts依赖 public class ClassABusiness { // 原ClassA中的业务方法 public void methodA() { // 业务逻辑代码 } } // 保留Struts调度职责的ClassA public class ClassA extends DispatchAction { private ClassABusiness business = new ClassABusiness(); public void methodA(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { business.methodA(); // 其他Struts相关调度逻辑 } }
对应测试类
@RunWith(JUnit4.class) public class TestClassABusiness { private ClassABusiness business = new ClassABusiness(); @Test public void testMethodA() { business.methodA(); // 断言或验证逻辑 } }
该方案既保证应用正常运行,又能轻松完成业务代码的覆盖率测试,完全规避Struts容器依赖问题。
2. 使用PowerMock抑制DispatchAction的静态初始化
若不想重构代码,可通过PowerMock拦截DispatchAction的静态初始化过程,避免触发依赖Struts容器的代码。
依赖准备
确保测试依赖包含PowerMock与JUnit4的适配包(以Maven为例):
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency>
修改测试类
@RunWith(PowerMockRunner.class) @SuppressStaticInitializationFor("org.apache.struts.actions.DispatchAction") public class TestClassA { @InjectMocks ClassA objA; // 声明需要Mock的依赖 @Before public void setUp() { MockitoAnnotations.openMocks(this); } @Test public void methodToTest() { objA.methodA(); // 验证逻辑 } }
@SuppressStaticInitializationFor注解会阻止DispatchAction的静态初始化代码执行,从根源上避免NPE。
3. 手动初始化Struts上下文(不推荐)
可在测试前手动初始化Struts必要资源,但该方式繁琐且依赖Struts内部实现细节,仅适合临时应急:
@Before public void setUp() { // 手动初始化MessageResources MessageResources resources = MessageResources.getMessageResources("your.struts.resource.path"); // 通过反射设置DispatchAction的静态变量 try { Field field = DispatchAction.class.getDeclaredField("messages"); field.setAccessible(true); field.set(null, resources); } catch (Exception e) { e.printStackTrace(); } MockitoAnnotations.openMocks(this); }
该方案对Struts版本依赖极强,维护成本高,不建议长期使用。
内容的提问来源于stack exchange,提问作者BEGINNER
相关产品推荐
相关产品推荐

