[英]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.