Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)

@PrepareForTest({AbstractController.class})

But I got the following error when running this test case. That is a static initializer in AbstractController.

Caused by: java.lang.NullPointerException at com.acompany.controller.common.AbstractController.(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(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

like image 945
Smartmarkey Avatar asked Sep 29 '11 03:09

Smartmarkey


People also ask

How do I fix ExceptionInInitializerError?

How to handle the ExceptionInInitializerError Error. To avoid this error, simply ensure that: static initializers of classes do not throw any unchecked exception, and that. static class variable initializations do not throw any unchecked exceptions.

How do I resolve Java Lang ExceptionInInitializerError in JUnit?

We can resolve the java. lang. ExceptionInInitializerError by ensuring that static initializer block of classes does not throw any Runtime Exception. We can resolve also resolve this exception by ensuring that the initializing static variable of classes also doesn't throw any Runtime Exception.

Can Mockito and PowerMock be used together?

Of course you can – and probably will – use Mockito and PowerMock in the same JUnit test at some point of time.


1 Answers

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:

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.

like image 155
MaDa Avatar answered Oct 31 '22 14:10

MaDa