使用Powermock模拟类的构造函数时得到ExceptionInInitializerError。 怎么解决?

这是我的情况。 我有一个AbstractController类。 它有一个子类控制器。 在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中的静态初始化程序。

引起: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上的java.lang.Class.forName0(本机方法)中的java.lang.ExceptionInInitializerError,javassist中的javasslang.runtime.Desc.getClassObject(Desc.java:44)中的java.lang.Class.forName(Class.java:169)。 run.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)在org.powermock.modules.junit4.internal的org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)的java.lang.reflect.Method.invoke(Method.java:597)。 impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:307)at org.junit.internal.runners.MethodRoadie $ 2.run(Me thodRoadie.java:86)org.junit.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)在org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)在org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl $ PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)在Org.junit.internal的org.junm上,在org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)的org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) .runners.MethodRoadie.run(MethodRoadie.java:49)org.powermock.modules.junit4.internal.impl.PowerMo ckJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)在org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)在org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ 1.run (PowerMockJUnit44RunnerDelegateImpl.java:120)org.junit.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)org.junit.runners.ClassRoadie.runProtected(ClassRoadie.java:44)org.powermock上的org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)。 modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)位于org.powermock.modules的org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102)。 junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)位于org.eclipse的org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)。 在org.eclipse.jdt.internal的org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)的jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)。 junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)位于org.eclipse.jdt.internal.junit.runner的org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)。 RemoteTestRunner.main(RemoteTestRunner.java:197)引起:com.acompany.controller.common.AbstractController中的java.lang.NullPointerException。(AbstractController.java:65)… 35更多

你可以使用:

  @SuppressStaticInitializationFor({AbstractController.class}) 

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

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

方法Class.getProtectionDomain()过分依赖于使用的类加载器,所以你可能不会让它在使用它们自己的JUnit / PowerMock中工作。