java - 使用 Powermock 模拟类的构造函数时出现 ExceptionInInitializerError。如何解决?

标签 java unit-testing testing powermock

这是我的案例。我有一个 AbstractController 类。它有一个子类Controller。在 AbstractController 的方法之一中,实例化了一个新的 ApplicationLock。我想在为 Controller 编写 ut 时模拟 ApplicationLock。我写了一个如下的测试用例。

@test
public void testMethod(){
    ApplicationLock mockLock=PowerMockito.mock(ApplicationLock.class);
    PowerMockito.when(mockLock.tryObtain()).thenReturn(true);
    PowerMockito.whenNew(ApplicationLock.class).withArguments(argThat(new IsFile()),anyString()).thenReturn(mockLock);
}

我已经为测试类添加了必要的注解。

@RunWith(PowerMockRunner.class)

@PrepareForTest({AbstractController.class})

但是我在运行这个测试用例的时候出现了如下错误。这是 AbstractController 中的静态初始化程序。

引起:java.lang.NullPointerException 在 com.acompany.controller.common.AbstractController.(AbstractController.java:65)

private static final String DEFAULT_FOLDER = AbstractController.class.getProtectionDomain().getCodeSource()
            .getLocation().getPath();

完整的堆栈跟踪如下。

java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at javassist.runtime.Desc.getClassObject(Desc.java:44) at javassist.runtime.Desc.getClassType(Desc.java:153) at javassist.runtime.Desc.getType(Desc.java:123) at javassist.runtime.Desc.getType(Desc.java:79) at com.acompany.controller.portfolio.ControllerTest.testIncrementalFail(ControllerTest.java:195) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:307) at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86) at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84) at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120) at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118) at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102) at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.NullPointerException at com.acompany.controller.common.AbstractController.(AbstractController.java:65) ... 35 more

最佳答案

然后你可以使用:

 @SuppressStaticInitializationFor({AbstractController.class})

然后,在您的测试用例中,手动设置所有需要初始化的静态字段,包​​括 DEFAULT_FOLDER:

Whitebox.setInternalState(Controller.class, "DEFAULT_FOLDER", "abcd");
Whitebox.setInternalState(Controller.class, "OTHER_FIELD", new Object());

方法Class<?>.getProtectionDomain()太多地依赖于使用的类加载器,因此您可能无法在使用它们自己的 JUnit/PowerMock 中使用它。

关于java - 使用 Powermock 模拟类的构造函数时出现 ExceptionInInitializerError。如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7592018/

相关文章:

java - 如何使用 selenium、junit 和 jenkins 执行性能测试

java - 当多个客户端尝试下载文件时,从 URL 下载的文件停止

java - 将 C 代码(32 位)与 Java 结合起来

javascript - 两个文件使用带有 mocha 的 supertest 导致 EADDRINUSE

unit-testing - 如何模拟 http.Client Do 方法

javascript - Mocha 测试用 .then stub 了 ajax 调用

java - 使用 Jetty servlet 容器测试 Jersey 端点在没有 session 的情况下失败

c++ - Boost.Test 测试静态库

java - 如何测试使用 LocalDateTime.now() 创建的日期

node.js - testcafe 通过 intelliJ run 操作执行