2

我正在尝试为调用的方法编写单元测试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;
}
4

2 回答 2

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 进行单元测试。

于 2013-10-27T16:50:23.437 回答
0

如果您无法模拟DriverManager.getConnection静态调用,可能的解决方法就是跳过它。

将静态调用提取到 sut 中的受保护方法,其签名与静态方法相同。

protected Connection driverManagerGetConnection(String url, String user, String password){
  return DriverManager.getConnection(url, user, password);
}

现在,在您的测试中,使用EasyMock 创建您的 sut 的部分模拟,模拟该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);
}

使用这种方法,唯一未测试的行是对静态方法的调用。

于 2013-10-28T11:23:13.437 回答