Mocking Static Methods

Mocking static methods with Mockito

Use PowerMockito on top of Mockito.

Example code:

@RunWith(PowerMockRunner.class)
@PrepareForTest(DriverManager.class)
public class Mocker {

@Test
public void shouldVerifyParameters() throws Exception {

//given
PowerMockito.mockStatic(DriverManager.class);
BDDMockito.given(DriverManager.getConnection(...)).willReturn(...);

//when
sut.execute(); // System Under Test (sut)

//then
PowerMockito.verifyStatic();
DriverManager.getConnection(...);

}

More information:

  • Why doesn't Mockito mock static methods?

Mokito/Java - Static Methods Mock

You should use try-with-resources block in each of the tests to close the mockStatic.

public class UsaTesteEstaticoTest {

UsaTesteEstatico usaTesteEstatico = new UsaTesteEstatico();

@Test
void teste1(){
try (var ms = Mockito.mockStatic(TesteEstatico.class)) {
Mockito.when(TesteEstatico.teste()).thenReturn("BANANA");
String res = usaTesteEstatico.metodoParaTeste1();
System.out.println(res);
}
}

@Test
void teste2(){
try (var ms = Mockito.mockStatic(TesteEstatico.class)) {
Mockito.when(TesteEstatico.teste()).thenReturn("LARANJA");
String res = usaTesteEstatico.metodoParaTeste2();
System.out.println(res);
}
}
}

Note on mockStatic in @BeforeAll

Using @BeforeAll is a trap and bad advice.
You should strive for independent tests that don't affect each other.
This is not the case for mockStatic called in @BeforeAll, as stubbing from test methods outlive the test methods.

For example

// BAD CODE DONT USE
public class UsaTesteEstaticoTest {

UsaTesteEstatico usaTesteEstatico = new UsaTesteEstatico();
static MockedStatic<TesteEstatico> ms;

@BeforeAll
public static void init() {
ms = Mockito.mockStatic(TesteEstatico.class);
}

@AfterAll
public static void close() {
ms.close();
}

@Test
void teste1() {
Mockito.when(TesteEstatico.teste()).thenReturn("BANANA");
String res = usaTesteEstatico.metodoParaTeste1();
System.out.println(res);
}

@Test
void teste2() {
String res = usaTesteEstatico.metodoParaTeste2();
System.out.println(res);
}
}

teste2 prints:

  • FOO BANANA BAR if run after teste1
  • FOO null BAR if run separately

This is precisely what you want to avoid.

How to mock static methods with more than one argument

In this particular case the any(String.class) fails to match the null passed when exercising the test

//...

VO vo = Factory.getObj("a", null);

//...

Use anyString()

//...

when(Factory.getObj(anyString(), anyString())).thenReturn(a);

Unable to mock System class static method using PowerMockito

java.net.InetAddress is a system class. The caller of the system class should be defined in @PrepareForTest({ClassThatCallsTheSystemClass.class}).

See documentation.

The way to go about mocking system classes are a bit different than
usual though. Normally you would prepare the class that contains the
static methods (let's call it X) you like to mock but because it's
impossible for PowerMock to prepare a system class for testing so
another approach has to be taken. So instead of preparing X you
prepare the class that calls the static methods in X!


Please note @InjectMocks annotation does not inject static mocks, it can be removed.

Example of working test:

@RunWith(PowerMockRunner.class)
@PrepareForTest(SCUtil.class)
public class SCUtilTest {

private SCUtil scUtil = new SCUtil();

@Test(expected = ServiceException.class)
public void testCreateSC_Exception () throws UnknownHostException {
PowerMockito.mockStatic(InetAddress.class);
PowerMockito.when(InetAddress.getLocalHost()).thenThrow(new UnknownHostException("test"));
scUtil.createSC();
}
}


Related Topics



Leave a reply



Submit