Jaykumar Jaykumar - 2 months ago 20
Java Question

Mocking Static method using PowerMockito

I am using PowerMockito to mock a static method to get a better line coverage. The test passes but Cobertura still shows the return line as red. I am not sure if I am using PowerMockito in a wrong way. Any clues?

MUT

public static Object getBean( String beanName ) {
return AppContext.getApplicationContext().getBean( beanName );
}


Junit test

@RunWith ( PowerMockRunner.class )
@PrepareForTest ( {AppContext.class} )

private ApplicationContext applicationContext;

@Test
public void testGetBean() throws Exception {
String beanName = "junitBean";
applicationContext = Mockito.mock(ApplicationContext.class);

PowerMockito.mockStatic(AppContext.class);

AppContext.setApplicationContext(applicationContext);
PowerMockito.when(AppContext.getApplicationContext()).thenReturn(applicationContext);
PowerMockito.when(AppContext.getApplicationContext().getBean(beanName)).thenReturn(Object.class);

AppContext.getBean(beanName);
}

Answer

To mock static methods, PowerMock has to modify the Java Byte Code of your class after it has been compiled. Code coverage tools work in the same way - they "instrument" (google for "bytecode instrumentation") the bytecode in order to collect information about which lines of code have been run.

Given that there are two things here modifying already compiled code according to their own needs, it's not surprising that they don't work well together. In fact, other coverage tools have the same issue e.g. this issue on the PowerMock GitHub page.

It is precisely reasons like this that mocking static methods is a bad idea and should only really be done in very exceptional circumstances. In most cases, you can either wrap the static method call in an interface and pass an instance of the interface to your object under test, or better yet (if the code is under your control) remove the static method and replace it with an instance method.

You could also just pass the ApplicationContext instance directly into the constructor of your class under test.

Comments