使用Powermock模拟类的构造函数时,出现ExceptionInInitializerError。如何解决?
这是我的情况。我有一个AbstractController类。它有一个子类Controller。在AbstractController的一种方法中,实例化了一个新的ApplicationLock。我想在为Controller编写ut时模拟ApplicationLock。我写了一个如下的测试用例。
Here is my case. I have a AbstractController class. It has a sub class Controller. In one of AbstractController's methods a new ApplicationLock is instantiated. I'd like to mock ApplicationLock when writing ut for Controller. I wrote a test case like below.
@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);
}
我已经在测试类中添加了必要的注释。
I've added necessary annotations to the test class.
@RunWith(PowerMockRunner.class)
@RunWith(PowerMockRunner.class)
@PrepareForTest({AbstractController.class})
@PrepareForTest({AbstractController.class})
但是运行此测试用例时出现以下错误。
But I got the following error when running this test case. That is a static initializer in AbstractController.
原因由:com.acompany.controller.common.AbstractController上的java.lang.NullPointerException
引起。 AbstractController.java:65)
private static final String DEFAULT_FOLDER = AbstractController.class.getProtectionDomain().getCodeSource()
.getLocation().getPath();
完整的堆栈跟踪如下。
java.lang.Class.forName(Class.java:169)在
java.lang.Class.forName0(Native Method)在
java.lang.Class.forName(Class.java:169)在
b $ b javassist.runtime.Desc.getClassObject(Desc.java:44)at
javassist.runtime.Desc.getClassType(Desc.java:153)at
javassist.runtime.Desc.getType(Desc .java:123)在
处javassist.runtime.Desc.getType(Desc.java:79)在
com.acompany.controller.portfolio.ControllerTest.testIncrementalFail(ControllerTest.java:195)
在
处sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
在
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl。 .java:25)java.lang.reflect.Method.invoke(Method.java:597)处的
org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66) )在
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:307)
在
org.junit.internal.runners.MethodRoadie在org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)在
org.powermock.modules处运行(MethodRoadie.java:86)
。 junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
在
org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ Power )
在
org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
在
org.powermock.modules.junit4 .internal.impl.PowerMo ckJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
在
org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:ternal)
in在org.org runners.MethodRoadie.run(MethodRoadie.java:49)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
在
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
在
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateI( PowerMockJUnit44RunnerDelegateImpl.java:120)
在
org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
在
org.junit.internal.runners。 ClassRoadie.runProtected(ClassRoadie.java:44)
在
org.powermock.modules.junit4.internal .impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
at
org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImplb.java:102:$102在
org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)在
org.eclipse.jdt.internal.junit4.runner的
。 JUnit4TestReference.run(JUnit4TestReference.java:49)
在
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
在
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java :683)
在
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
在
org.eclipse.jdt.internal .junit.runner.RemoteTestRunner.main(RemoteTestRunner.j ava:197)
原因:
处的java.lang.NullPointerException com.acompany.controller.common.AbstractController。(AbstractController.java:65)
... 35更多
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:
And then, in your test case, set manually all static fields that need to be initialized, including the DEFAULT_FOLDER:
Whitebox.setInternalState(Controller.class, "DEFAULT_FOLDER", "abcd");
Whitebox.setInternalState(Controller.class, "OTHER_FIELD", new Object());
方法 Class<?> .getProtectionDomain()
在很大程度上取决于所使用的类加载器,因此您可能无法在使用它们的JUnit / PowerMock中使用它。
The method Class<?>.getProtectionDomain()
depends too much on class loader used, so you probably won't get it to work in JUnit/PowerMock, which use their own.