Mocking Static Methods With Mockito

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?

How to Mock a static method with mockito?

Since static method belongs to the class, there is no way in Mockito to mock static methods. However, you can use PowerMock along with Mockito framework to mock static methods.

A simple class with a static method:

public class Utils {

public static boolean print(String msg) {
System.out.println(msg);

return true;
}
}

Class test mocking static method using Mockito and PowerMock in JUnit test case:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class JUnit4PowerMockitoStaticTest{

@Test
public void test_static_mock_methods() {
PowerMockito.mockStatic(Utils.class);
when(Utils.print("Hello")).thenReturn(true);
when(Utils.print("Wrong Message")).thenReturn(false);

assertTrue(Utils.print("Hello"));
assertFalse(Utils.print("Wrong Message"));

PowerMockito.verifyStatic(Utils.class, atLeast(2));
Utils.print(anyString());
}
}

For more details see this link.

How to mock just one static method in a class using Mockito?

By default all methods are mocked. However, using Mockito.CALLS_REAL_METHODS you can configure the mock to actually trigger the real methods excluding only one.

For example given the class Sample:

class Sample{
static String method1(String s) {
return s;
}
static String method2(String s) {
return s;
}
}

If we want to mock only method1:

@Test
public void singleStaticMethodTest(){
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
mocked.when(() -> Sample.method1(anyString())).thenReturn("bar");
assertEquals("bar", Sample.method1("foo")); // mocked
assertEquals("foo", Sample.method2("foo")); // not mocked
}
}

Be aware that the real Sample.method1() will still be called. From Mockito.CALLS_REAL_METHODS docs:

This implementation can be helpful when working with legacy code. When
this implementation is used, unstubbed methods will delegate to the
real implementation. This is a way to create a partial mock object
that calls real methods by default.
...

Note 1: Stubbing partial mocks using
when(mock.getSomething()).thenReturn(fakeValue) syntax will call the
real method. For partial mock it's recommended to use doReturn
syntax.

So if you don't want to trigger the stubbed static method at all, the solution would be to use the syntax doReturn (as the doc suggests) but for static methods is still not supported:

@Test
public void singleStaticMethodTest() {
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
doReturn("bar").when(mocked).method1(anyString()); // Compilation error!
//...
}
}

About this there is an open issue, in particular check this comment.

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