Search code examples
javajunitmockitopowermockpowermockito

Use PowerMock to prevent static initialization


So I have a static variable in my class under test. I have tried to mock it With Powermockito but I am getting error.

public class ClassUnderTest{
  private static EntityManager em = AppEntityManager.createEntityManager();
   public static String methodUnderTest(){
       // this method dosent use EntityManager em
   }
}

My test class is like this:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ AppEntityManager.class, ClassUnderTest.class })

public class ClassUnderTestTest {
 @Mock
 private EntityManager emMock;
 @InjectMocks
 private ClassUnderTest feMock;

 static ClassUnderTest fe = new ClassUnderTest();

 @Before
 public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
 }

 @Test
 public void test() {
     PowerMockito.mockStatic(ClassUnderTest.class);
    PowerMockito.mockStatic(AppEntityManager.class);
    Mockito.when(AppEntityManager.createEntityManager()).thenReturn(emMock);


        String s = ClassUnderTest.methodUnderTest(myParams);
        // assertEquals(prams[i][1], s);
        System.out.println(s);

  }

}

The error is

Feb 22, 2018 9:37:31 AM oracle.jdbc.driver.OracleDriver registerMBeans
SEVERE: Error while registering Oracle JDBC Diagnosability MBean.
java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/MockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer"

Can you tell me where I am going wrong? I just want to test methodUnderTest() and so is there a way I can prevent that static initialization of EntityManager em?


Solution

  • This code works for me

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({ AppEntityManager.class}) 
    public class ClassUnderTestTest {
    
      @Mock
      private EntityManager emMock;
    
      @Before
      public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
      }
    
      @Test
      public void test() {
        PowerMockito.mockStatic(AppEntityManager.class);
        Mockito.when(AppEntityManager.createEntityManager()).thenReturn(emMock);
    
        String s = ClassUnderTest.methodUnderTest(myParams);
        // assertEquals(prams[i][1], s);
      }
    
    }
    

    Some points

    1. Since EntityManager is not @Aurowired, there is no need for @InjectMocks.
    2. Since you want the code under ClassUnderTest::methodUnderTest to be called, don't use ClassUnderTest in @PrepareForTest
    3. Don't do PowerMockito.mockStatic(ClassUnderTest.class);

    Having said all of these. You should seriously consider refactoring your code to minimize(if possible eliminate) all static methods and fields.