簡體   English   中英

使用PowerMock和Mockito模擬靜態方法

[英]Mocking static methods with PowerMock and Mockito

我正在嘗試使用JUnit,Mockito和PowerMock驗證對java.sql.DriverManager.getConnection的調用。

這是我的測試用例:

@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");
    }

}

這是測試中的代碼:

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);
        }
    }
}

有趣的是,這段代碼失敗了java.sql.SQLException

java.lang.RuntimeException: java.sql.SQLException: No suitable driver found for jdbc:mysql://myhost:1111/database

現在,我可以很容易地確保我的SQL驅動程序(在這種情況下是MySQL)在測試時加載,但為什么靜態方法沒有完全模擬掉沒有副作用?

更新:

我最好隔離這個問題。 我在測試用例中添加了一個測試方法,嘗試從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");
}

此測試實際通過,而另一個測試仍然失敗。 似乎PowerMock沒有模擬對MySQLDatabaseConnectionFactory內部類的引用。 我該如何解決這個問題?

@PrepareForTest注釋值更改為MySQLDatabaseConnectionFactory.class將解決此問題。

此注釋告訴PowerMock准備某些類以進行測試。 需要使用此批注定義的類通常是需要進行字節碼操作的類。 這包括最終類,最終類,私有類,靜態類。

在這種情況下,PowerMockito必須使用模擬代碼將調用替換為靜態方法DriverManager.getConnection 這是通過使用字節碼操作完成的。

完整代碼

@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");
    }
}

感謝@Szpak幫助我解決了這個問題!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM