我正在尝试为一个名为DriverManager.getConnection()
的方法编写单元测试。我正在使用PowerMock 1.5和easymock。不知何故,Powermock无法模拟DriverManager并最终调用真正的DriverManager。
这就是我的代码的样子: -
@Test
public void checkConnection() {
try {
String url = "jdbc:oracle:thin:@//myhost:1521/orcl";
String password = "@55";
String dbName = "Halloween";
String username = "Dracula";
PowerMock.mockStatic(DriverManager.class);
Connection connection = EasyMock.createMock(Connection.class);
List<Datasource> allDs = new ArrayList<Datasource>(2);
Datasource d1 = new Datasource();
d1.setUrl(url);
allDs.add(d1);
allDs.add(new Datasource());
EasyMock.expect(hibernateTemplate.find("from Datasource ds where ds.dsName = ?", dbName)).andReturn(allDs);
EasyMock.expect(DriverManager.getConnection(d1.getUrl(), username, password)).andReturn(connection);
PowerMock.replay(DriverManager.class);
EasyMock.replay(hibernateTemplate);
Connection con = testee.authenticateUserForDatabase(dbName, username, password);
Assert.assertNotNull(con);
PowerMock.verify(DriverManager.class);
EasyMock.verify(hibernateTemplate);
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
我的班级代码如下所示: -
@Override
public Connection getConnection(String dbName, String username, String password) {
Connection connection = null;
@SuppressWarnings("unchecked")
List<Datasource> ds = hibernateTemplate.find("from Datasource ds where ds.dsName = ?", dbName);
if (ds == null || ds.isEmpty()) {
throw new ProviderException("Invalid datasource name [" + dbName + "]");
}
Datasource d = (Datasource) ds.get(0);
int retryCount = 0;
boolean connected = false;
while (retryCount < 2 && !connected) {
try {
connection = DriverManager.getConnection(d.getUrl(), username, password);
LOG.info("Connected successfully to [{}]", dbName);
connected = true;
} catch (SQLException e) {
LOG.warn("Error: [{}] occured. Going to retry, attempt # [{}]", e.getMessage(), (retryCount + 1));
retryCount++;
connected = false;
}
}
return connection;
}
答案 0 :(得分:0)
您可以使用javax.sql.DataSource而不是使用DriverManager。
http://docs.oracle.com/javase/6/docs/api/javax/sql/DataSource.html
这样,您正在使用可以模拟的界面。目前大多数应用程序都使用DataSource接口,并且不像这样与DriverManager交互。
所以你的代码可以有一个api:
public class DataSourceFactory {
public DataSource getDataSource( String url, String usr, String pwd);
}
如果您愿意,可以使用DriverManager实现真正的DataSource,然后模拟DataSourceFactory进行单元测试。
答案 1 :(得分:0)
如果您无法模拟DriverManager.getConnection
静态调用,可能的解决方法就是跳过它。
使用与静态方法相同的签名将静态调用提取到sut中受保护的方法。
protected Connection driverManagerGetConnection(String url, String user, String password){
return DriverManager.getConnection(url, user, password);
}
现在,在您的测试中,使用您的sut的EasyMock to create a partial mock,嘲笑driverManagerGetConnection
方法。
public void testFoo{
// setup: sut
YourSutClass sut = EasyMock.createMockBuilder(YourSutClass.class)
.addMockedMethod("driverManagerGetConnection").createMock();
...
// setup: expectations
EasyMock.expect(sut.driverManagerGetConnection()).andReturn(mockConnection);
...
// exercise
EasyMock.replay(sut, mockConnection);
sut.whatever();
// verify
EasyMock.verify(sut, mockConnection);
}
使用这种方法,您未经测试的唯一一行是对静态方法的调用。