简体   繁体   English

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

[英]Got ExceptionInInitializerError when mocking constructor of a class with Powermock. How to fix it?

Here is my case. 这是我的情况。 I have a AbstractController class. 我有一个AbstractController类。 It has a sub class Controller. 它有一个子类控制器。 In one of AbstractController's methods a new ApplicationLock is instantiated. 在AbstractController的一个方法中,实例化了一个新的ApplicationLock。 I'd like to mock ApplicationLock when writing ut for Controller. 我想在为Controller编写ut时模拟ApplicationLock。 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. 这是AbstractController中的静态初始化程序。

Caused by: java.lang.NullPointerException at com.acompany.controller.common.AbstractController.(AbstractController.java:65) 引起:com.acompany.controller.common.AbstractController中的java.lang.NullPointerException。(AbstractController.java:65)

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

Full stack trace is as below. 完整堆栈跟踪如下。

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(Me java.lang上的java.lang.Class.forName0(本机方法)中的java.lang.ExceptionInInitializerError,javassist上的javassist.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) 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.PowerMo 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.runner.MethodRoadie.runTest(MethodRoadie.java:84)的org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl $ PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) .runners.MethodRoadie.run(MethodRoadie.java:49)at org.powermock.modules.junit4.internal.impl.PowerMo ckJUnit44RunnerDelegateImpl.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. 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)。 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 在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更多

You could use then: 你可以使用:

 @SuppressStaticInitializationFor({AbstractController.class})

And then, in your test case, set manually all static fields that need to be initialized, including the DEFAULT_FOLDER: 然后,在您的测试用例中,手动设置需要初始化的所有静态字段,包​​括DEFAULT_FOLDER:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM