[java] Mocking static methods with Mockito

I've written a factory to produce java.sql.Connection objects:

public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory {

    @Override public Connection getConnection() {
        try {
            return DriverManager.getConnection(...);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

I'd like to validate the parameters passed to DriverManager.getConnection, but I don't know how to mock a static method. I'm using JUnit 4 and Mockito for my test cases. Is there a good way to mock/verify this specific use-case?

This question is related to java unit-testing static mocking mockito

The answer is


Mocking of static methods in Mockito is possible since Mockito 3.4.0. For more details see:

https://github.com/mockito/mockito/releases/tag/v3.4.0

https://github.com/mockito/mockito/issues/1013.

In your case, something like this:

  @Test
  public void testStaticMockWithVerification() throws SQLException {
    try (MockedStatic<DriverManager> dummy = Mockito.mockStatic(DriverManager.class)) {
      DatabaseConnectionFactory factory = new MySQLDatabaseConnectionFactory();
      dummy.when(() -> DriverManager.getConnection("arg1", "arg2", "arg3"))
        .thenReturn(new Connection() {/*...*/});

      factory.getConnection();

      dummy.verify(() -> DriverManager.getConnection(eq("arg1"), eq("arg2"), eq("arg3")));
    }
  }

NOTE: this feature requires mockito-inline dependency.


For mocking static functions i was able to do it that way:

  • create a wrapper function in some helper class/object. (using a name variant might be beneficial for keeping things separated and maintainable.)
  • use this wrapper in your codes. (Yes, codes need to be realized with testing in mind.)
  • mock the wrapper function.

wrapper code snippet (not really functional, just for illustration)

class myWrapperClass ...
    def myWrapperFunction (...) {
        return theOriginalFunction (...)
    }

of course having multiple such functions accumulated in a single wrapper class might be beneficial in terms of code reuse.


You can do it with a little bit of refactoring:

public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory {

    @Override public Connection getConnection() {
        try {
            return _getConnection(...some params...);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    //method to forward parameters, enabling mocking, extension, etc
    Connection _getConnection(...some params...) throws SQLException {
        return DriverManager.getConnection(...some params...);
    }
}

Then you can extend your class MySQLDatabaseConnectionFactory to return a mocked connection, do assertions on the parameters, etc.

The extended class can reside within the test case, if it's located in the same package (which I encourage you to do)

public class MockedConnectionFactory extends MySQLDatabaseConnectionFactory {

    Connection _getConnection(...some params...) throws SQLException {
        if (some param != something) throw new InvalidParameterException();

        //consider mocking some methods with when(yourMock.something()).thenReturn(value)
        return Mockito.mock(Connection.class);
    }
}

For those who use JUnit 5, Powermock is not an option. You'll require the following dependencies to successfully mock a static method with just Mockito.

testCompile    group: 'org.mockito', name: 'mockito-core',           version: '3.6.0'
testCompile    group: 'org.mockito', name: 'mockito-junit-jupiter',  version: '3.6.0'
testCompile    group: 'org.mockito', name: 'mockito-inline',         version: '3.6.0'

mockito-junit-jupiter add supports for JUnit 5.

And support for mocking static methods is provided by mockito-inline dependency.

Example:

@Test
void returnUtilTest() {
    assertEquals("foo", UtilClass.staticMethod("foo"));

    try (MockedStatic<UtilClass> classMock = mockStatic(UtilClass.class)) {

        classMock.when(() -> UtilClass.staticMethod("foo")).thenReturn("bar");

        assertEquals("bar", UtilClass.staticMethod("foo"));
     }

     assertEquals("foo", UtilClass.staticMethod("foo"));
}

The try-with-resource block is used to make the static mock remains temporary, so it's mocked only within that scope.

When not using a try block, make sure to close the scoped mock, once you are done with the assertions.

MockedStatic<UtilClass> classMock = mockStatic(UtilClass.class)
classMock.when(() -> UtilClass.staticMethod("foo")).thenReturn("bar");
assertEquals("bar", UtilClass.staticMethod("foo"));
classMock.close();

Mocking void methods:

When mockStatic is called on a class, all the static void methods in that class automatically get mocked to doNothing().


There is an easy solution by using java FunctionalInterface and then add that interface as dependency for the class you are trying to unit test.


To mock static method you should use a Powermock look at: https://github.com/powermock/powermock/wiki/MockStatic. Mockito doesn't provide this functionality.

You can read nice a article about mockito: http://refcardz.dzone.com/refcardz/mockito


Mockito cannot capture static methods, but since Mockito 2.14.0 you can simulate it by creating invocation instances of static methods.

Example (extracted from their tests):

public class StaticMockingExperimentTest extends TestBase {

    Foo mock = Mockito.mock(Foo.class);
    MockHandler handler = Mockito.mockingDetails(mock).getMockHandler();
    Method staticMethod;
    InvocationFactory.RealMethodBehavior realMethod = new InvocationFactory.RealMethodBehavior() {
        @Override
        public Object call() throws Throwable {
            return null;
        }
    };

    @Before
    public void before() throws Throwable {
        staticMethod = Foo.class.getDeclaredMethod("staticMethod", String.class);
    }

    @Test
    public void verify_static_method() throws Throwable {
        //register staticMethod call on mock
        Invocation invocation = Mockito.framework().getInvocationFactory().createInvocation(mock, withSettings().build(Foo.class), staticMethod, realMethod,
                "some arg");
        handler.handle(invocation);

        //verify staticMethod on mock
        //Mockito cannot capture static methods so we will simulate this scenario in 3 steps:
        //1. Call standard 'verify' method. Internally, it will add verificationMode to the thread local state.
        //  Effectively, we indicate to Mockito that right now we are about to verify a method call on this mock.
        verify(mock);
        //2. Create the invocation instance using the new public API
        //  Mockito cannot capture static methods but we can create an invocation instance of that static invocation
        Invocation verification = Mockito.framework().getInvocationFactory().createInvocation(mock, withSettings().build(Foo.class), staticMethod, realMethod,
                "some arg");
        //3. Make Mockito handle the static method invocation
        //  Mockito will find verification mode in thread local state and will try verify the invocation
        handler.handle(verification);

        //verify zero times, method with different argument
        verify(mock, times(0));
        Invocation differentArg = Mockito.framework().getInvocationFactory().createInvocation(mock, withSettings().build(Foo.class), staticMethod, realMethod,
                "different arg");
        handler.handle(differentArg);
    }

    @Test
    public void stubbing_static_method() throws Throwable {
        //register staticMethod call on mock
        Invocation invocation = Mockito.framework().getInvocationFactory().createInvocation(mock, withSettings().build(Foo.class), staticMethod, realMethod,
                "foo");
        handler.handle(invocation);

        //register stubbing
        when(null).thenReturn("hey");

        //validate stubbed return value
        assertEquals("hey", handler.handle(invocation));
        assertEquals("hey", handler.handle(invocation));

        //default null value is returned if invoked with different argument
        Invocation differentArg = Mockito.framework().getInvocationFactory().createInvocation(mock, withSettings().build(Foo.class), staticMethod, realMethod,
                "different arg");
        assertEquals(null, handler.handle(differentArg));
    }

    static class Foo {

        private final String arg;

        public Foo(String arg) {
            this.arg = arg;
        }

        public static String staticMethod(String arg) {
            return "";
        }

        @Override
        public String toString() {
            return "foo:" + arg;
        }
    }
}

Their goal is not to directly support static mocking, but to improve its public APIs so that other libraries, like Powermockito, don't have to rely on internal APIs or directly have to duplicate some Mockito code. (source)

Disclaimer: Mockito team thinks that the road to hell is paved with static methods. However, Mockito's job is not to protect your code from static methods. If you don’t like your team doing static mocking, stop using Powermockito in your organization. Mockito needs to evolve as a toolkit with an opinionated vision on how Java tests should be written (e.g. don't mock statics!!!). However, Mockito is not dogmatic. We don't want to block unrecommended use cases like static mocking. It's just not our job.


Use JMockit framework. It worked for me. You don't have to write statements for mocking DBConenction.getConnection() method. Just the below code is enough.

@Mock below is mockit.Mock package

Connection jdbcConnection = Mockito.mock(Connection.class);

MockUp<DBConnection> mockUp = new MockUp<DBConnection>() {

            DBConnection singleton = new DBConnection();

            @Mock
            public DBConnection getInstance() { 
                return singleton;
            }

            @Mock
            public Connection getConnection() {
                return jdbcConnection;
            }
         };

I also wrote a combination of Mockito and AspectJ: https://github.com/iirekm/varia/tree/develop/ajmock

Your example becomes:

when(() -> DriverManager.getConnection(...)).thenReturn(...);

As mentioned before you can not mock static methods with mockito.

If changing your testing framework is not an option you can do the following:

Create an interface for DriverManager, mock this interface, inject it via some kind of dependency injection and verify on that mock.


I had a similar issue. The accepted answer did not work for me, until I made the change: @PrepareForTest(TheClassThatContainsStaticMethod.class), according to PowerMock's documentation for mockStatic.

And I don't have to use BDDMockito.

My class:

public class SmokeRouteBuilder {
    public static String smokeMessageId() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            log.error("Exception occurred while fetching localhost address", e);
            return UUID.randomUUID().toString();
        }
    }
}

My test class:

@RunWith(PowerMockRunner.class)
@PrepareForTest(SmokeRouteBuilder.class)
public class SmokeRouteBuilderTest {
    @Test
    public void testSmokeMessageId_exception() throws UnknownHostException {
        UUID id = UUID.randomUUID();

        mockStatic(InetAddress.class);
        mockStatic(UUID.class);
        when(InetAddress.getLocalHost()).thenThrow(UnknownHostException.class);
        when(UUID.randomUUID()).thenReturn(id);

        assertEquals(id.toString(), SmokeRouteBuilder.smokeMessageId());
    }
}

Observation : When you call static method within a static entity, you need to change the class in @PrepareForTest.

For e.g. :

securityAlgo = MessageDigest.getInstance(SECURITY_ALGORITHM);

For the above code if you need to mock MessageDigest class, use

@PrepareForTest(MessageDigest.class)

While if you have something like below :

public class CustomObjectRule {

    object = DatatypeConverter.printHexBinary(MessageDigest.getInstance(SECURITY_ALGORITHM)
             .digest(message.getBytes(ENCODING)));

}

then, you'd need to prepare the class this code resides in.

@PrepareForTest(CustomObjectRule.class)

And then mock the method :

PowerMockito.mockStatic(MessageDigest.class);
PowerMockito.when(MessageDigest.getInstance(Mockito.anyString()))
      .thenThrow(new RuntimeException());

Since that method is static, it already has everything you need to use it, so it defeats the purpose of mocking. Mocking the static methods is considered to be a bad practice.

If you try to do that, it means there is something wrong with the way you want to perform testing.

Of course you can use PowerMockito or any other framework capable of doing that, but try to rethink your approach.

For example: try to mock/provide the objects, which that static method consumes instead.


The typical strategy for dodging static methods that you have no way of avoiding using, is by creating wrapped objects and using the wrapper objects instead.

The wrapper objects become facades to the real static classes, and you do not test those.

A wrapper object could be something like

public class Slf4jMdcWrapper {
    public static final Slf4jMdcWrapper SINGLETON = new Slf4jMdcWrapper();

    public String myApisToTheSaticMethodsInSlf4jMdcStaticUtilityClass() {
        return MDC.getWhateverIWant();
    }
}

Finally, your class under test can use this singleton object by, for example, having a default constructor for real life use:

public class SomeClassUnderTest {
    final Slf4jMdcWrapper myMockableObject;

    /** constructor used by CDI or whatever real life use case */
    public myClassUnderTestContructor() {
        this.myMockableObject = Slf4jMdcWrapper.SINGLETON;
    }

    /** constructor used in tests*/
    myClassUnderTestContructor(Slf4jMdcWrapper myMock) {
        this.myMockableObject = myMock;
    }
}

And here you have a class that can easily be tested, because you do not directly use a class with static methods.

If you are using CDI and can make use of the @Inject annotation then it is even easier. Just make your Wrapper bean @ApplicationScoped, get that thing injected as a collaborator (you do not even need messy constructors for testing), and go on with the mocking.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to unit-testing

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0 How to test the type of a thrown exception in Jest Unit Tests not discovered in Visual Studio 2017 Class Not Found: Empty Test Suite in IntelliJ Angular 2 Unit Tests: Cannot find name 'describe' Enzyme - How to access and set <input> value? Mocking HttpClient in unit tests Example of Mockito's argumentCaptor How to write unit testing for Angular / TypeScript for private methods with Jasmine Why is the Visual Studio 2015/2017/2019 Test Runner not discovering my xUnit v2 tests

Examples related to static

What is the equivalent of Java static methods in Kotlin? Creating a static class with no instances Static vs class functions/variables in Swift classes? Call static methods from regular ES6 class methods What is the difference between static func and class func in Swift? An object reference is required to access a non-static member Mocking static methods with Mockito @Autowired and static method The static keyword and its various uses in C++ Non-Static method cannot be referenced from a static context with methods and variables

Examples related to mocking

How can I mock the JavaScript window object using Jest? How can I mock an ES6 module import using Jest? Mocking a function to raise an Exception to test an except block Unfinished Stubbing Detected in Mockito Python mock multiple return values How do I mock a service that returns promise in AngularJS Jasmine unit test? How do Mockito matchers work? Mocking static methods with Mockito How to spyOn a value property (rather than a method) with Jasmine How do I mock a class without an interface?

Examples related to mockito

How to resolve Unneccessary Stubbing exception How do I mock a REST template exchange? Mockito : doAnswer Vs thenReturn Example of Mockito's argumentCaptor Mockito: Mock private field initialization Mockito - NullpointerException when stubbing Method Usages of doThrow() doAnswer() doNothing() and doReturn() in mockito Java verify void method calls n times with Mockito Unfinished Stubbing Detected in Mockito How do I mock an autowired @Value field in Spring with Mockito?