Mocking static methods with PowerMock and Mockito

java, junit, mockito, powermock, unit-testing

Solution

Changing your `@PrepareForTest` annotation value to `MySQLDatabaseConnectionFactory.class` will resolve this issue.

This annotation tells PowerMock to prepare certain classes for testing. Classes needed to be defined using this annotation are typically those that needs to be byte-code manipulated. This includes final classes, classes with final, private, static.

In this situation PowerMockito have to replace invocation to static method `DriverManager.getConnection` with mocked code. This is done with usage of byte-code manipulation.

Full code

@RunWith(PowerMockRunner.class)
@PrepareForTest(MySQLDatabaseConnectionFactory.class)
public class MySQLDatabaseConnectionFactoryTest {

    private MySQLDatabaseConnectionFactory reference;

    @Before
    public void setUp() throws Exception {
        reference = new MySQLDatabaseConnectionFactory();
    }

    @Test
    public void testGetConnection() throws SQLException {

        // given
        PowerMockito.mockStatic(DriverManager.class);
        BDDMockito.given(DriverManager.getConnection(anyString(), anyString(), anyString()))
             .willReturn(mock(Connection.class));

        // when
        reference.getConnection();

        // then
        PowerMockito.verifyStatic();
        DriverManager.getConnection("jdbc:mysql://myhost:1111/database", "username", "password");
    }
}

Thanks to @Szpak for helping me to resolve this issue!

Problem

I'm trying to verify a call to `java.sql.DriverManager.getConnection` using JUnit, Mockito, and PowerMock. Here's my test case: ``` @RunWith(PowerMockRunner.class) @PrepareForTest(DriverManager.class) public class MySQLDatabaseConnectionFactoryTest { private ConfigurationService configurationService; private MySQLDatabaseConnectionFactory reference; @Before public void setUp() throws Exception { this.reference = new MySQLDatabaseConnectionFactory(); } @Test public void testGetConnection() throws SQLException { // setup Connection connection = mock(Connection.class); PowerMockito.mockStatic(DriverManager.class); when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(connection); // run this.reference.getConnection(); // verify PowerMockito.verifyStatic(); DriverManager.getConnection("jdbc:mysql://myhost:1111/database", "username", "password"); } } ``` Here's the code under test: ``` public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory { @Override public Connection getConnection(IApplicationInstance appInstance) { try { return DriverManager.getConnection(String.format("jdbc:mysql://%s:%d/%s", MYSQL_HOST, MYSQL_PORT, MYSQL_DATABASE), MYSQL_USERNAME, MYSQL_PASSWORD); } catch (SQLException e) { throw new RuntimeException(e); } } } ``` Interestingly enough, this code fails with a `java.sql.SQLException`: ``` java.lang.RuntimeException: java.sql.SQLException: No suitable driver found for jdbc:mysql://myhost:1111/database ``` Now, I could easily just make sure that my SQL driver (MySQL in this case) is loaded at test time, but why isn't the static method completely mocked out without side-effects? Update: I've better isolated the problem. I've added a test method to my test case which tries getting a connection from `DriverManager`: ``` @Test public void testSomething() { Connection conn = mock(Connection.class); mockStatic(DriverManager.class); when(DriverManager.getConnection(anyString())).thenReturn(conn); Connection c = DriverManager.getConnection("whut"); verifyStatic(); DriverManager.getConnection("whut"); } ``` This test actually passes, while the other test still fails. It seems that PowerMock isn't mocking the reference to the class inside of `MySQLDatabaseConnectionFactory`. How can I work around this?

Original source