Search code examples
javaspringjunitpowermockpowermockito

Powermock ExceptionInInitializerError with Junit


Unit Test setup

@RunWith(PowerMockRunner.class)
@PrepareForTest(PGWService.class)
public class PGWServiceTest {
public static final String TEST_CLIENTTRX_ID = "12345";
public static final int TEST_SITE_ID = 0;
public static final long TEST_USER_ID = 12345L;
public static final int TEST_CURRENCY_ID = 1;
public static final String TEST_ACCOUNT_TYPE = "Test account type";
public static final boolean TEST_IS_DEDUPING = false;
public static final byte[] TEST_SSN_CRYPT = new byte[] { 1, 2, 3 };
public static final byte[] TEST_TAX_ID_CRYPT = new byte[] { 1, 2, 3 };
public static final String TEST_SSN_LAST_FOUR = "1234";
public static final String TEST_TAX_ID_LAST_FOUR = "1234";

@Mock
PGWBaseRequest request;

@Mock
PGWClient client;

PGWService pGWService = new PGWService();

PGWGetAccountTaxIDResponse expectedResponse = this
        .buildGPWGetAccountIdResponse(TEST_SSN_CRYPT, TEST_TAX_ID_CRYPT,
                TEST_SSN_LAST_FOUR, TEST_TAX_ID_LAST_FOUR);

@Before
public void setUp() throws Exception {
    PowerMockito.mockStatic(PGWClient.class);
    PowerMockito.mockStatic(PGWBaseRequest.class);
    PowerMockito.when(PGWClient.getInstance()).thenReturn(client);
    PowerMockito
            .whenNew(PGWBaseRequest.class)
            .withArguments(TEST_CLIENTTRX_ID, TEST_SITE_ID, TEST_USER_ID,
                    TEST_CURRENCY_ID, TEST_ACCOUNT_TYPE, TEST_IS_DEDUPING)
            .thenReturn(request);
    PowerMockito.when(client.getTaxIdInformation(request)).thenReturn(
            expectedResponse);
}

@Test
public void testGetTaxIdInformationHappyPath() throws PGWException {

    PGWGetAccountTaxIDResponse actualResponse = pGWService
            .getTaxIdInformation(TEST_CLIENTTRX_ID, TEST_SITE_ID,
                    TEST_USER_ID, TEST_CURRENCY_ID, TEST_ACCOUNT_TYPE,
                    TEST_IS_DEDUPING);
    Assert.assertEquals(expectedResponse.getSSNLastFour(),
            actualResponse.getSSNLastFour());
}

private PGWGetAccountTaxIDResponse buildGPWGetAccountIdResponse(
        byte[] ssnCrypt, byte[] taxIdCrypt, String ssnLastFour,
        String taxIdLastFour) {
    PGWGetAccountTaxIDResponse response = new PGWGetAccountTaxIDResponse();
    response.setSSNCrypt(ssnCrypt);
    response.setSSNLastFour(ssnLastFour);
    response.setTaxIDCrypt(taxIdCrypt);
    response.setTaxIDLastFour(taxIdLastFour);
    return response;

}

}

I tried to run the unit test, it failed in the test instantiate with the following error

java.lang.ExceptionInInitializerError at sun.reflect.GeneratedSerializationConstructorAccessor7.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:40) at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:59) at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128) at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:63) at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:111) at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:60) at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:143) at org.powermock.api.extension.listener.AnnotationEnabler.standardInject(AnnotationEnabler.java:84) at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:51) at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:90) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:292) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127) at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82) 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:104) at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Caused by: java.lang.NullPointerException at at com.bdd.domain.biz.pgwclient.DynamicConfigListener.getAttributeValue(DynamicConfigListener.java:132) at com.bdd.domain.biz.pgwclient.PGWCommunicator.init(PGWCommunicator.java:95) at com.ebay.domain.biz.pgwclient.PGWCommunicator.(PGWCommunicator.java:83) at com.bdd.domain.biz.pgwclient.PGWCommunicator.getInstance(PGWCommunicator.java:62) at com.bdd.domain.biz.pgwclient.PGWClient.(PGWClient.java:117)


Solution

  • When you are trying to mock static methods with PowerMock it internally creates an instance of the class. So when you

    PowerMockito.mockStatic(PGWClient.class);
    

    New instance of the class is created inside PowerMock. Your PGWClient class default constructor does some initialization calling static methods at this moment. This causes static mocking to fail.

    You should check on Power Mock Suppressing Unwanted Behavior


    EDIT

    From stack trace it can be seen that PGWClient is accessing instance of PGWCommunicator via getInstance method. There is some unwanted behaviour inside. You can

    1. Suppress its behaviour using info from link above
    2. Create a default (package) or protected setInstance method to replace object returned during tests
    3. Ideally move from singleton instance fetters to DI. Such code is a way more testable.