如何模拟DriverManager.getConnection(…)?

我有一个类,它连接到H2数据库并运行几个SQL语句。

public class H2Persistence implements IPersistence { private Connection conn; @Override public void open() { try { Class.forName("org.h2.Driver"); conn = DriverManager.getConnection(CONN_TYPE_USER_HOME); final Statement stmt = conn.createStatement(); stmt.executeUpdate("CREATE TABLE PERSON(" + "ID BIGINT,"+ "AGEGROUP VARCHAR(255),"+ "MONTHLY_INCOME_LEVEL VARCHAR(255)," + "GENDER VARCHAR(1),"+ "HOUSEHOLD_ID BIGINT)"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } ... } 

我想编写一个unit testing,它validation在open方法中执行某个SQL语句( DROP TABLE IF EXISTS PERSON )。

为了做到这一点,我写了以下测试:

 import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @RunWith(PowerMockRunner.class) @PrepareForTest(DriverManager.class) public class H2PersistenceTest { @Test public void testDropPersonIsCalled() throws SQLException { final Statement statement = mock(Statement.class); final Connection connection = mock(Connection.class); when(connection.createStatement()).thenReturn(statement); mockStatic(DriverManager.class); when(DriverManager.getConnection(H2Persistence.CONN_TYPE_USER_HOME)).thenReturn (connection); final H2Persistence objectUnderTest = new H2Persistence(); objectUnderTest.open(); verify(statement.executeUpdate("DROP TABLE IF EXISTS PERSON")); } } 

但它不起作用 – 而不是模拟连接, DriverManager返回真正的连接。

我该如何解决它(在测试中使DriverManager返回连接模拟)?

这是我项目的pom.xml ,也许有些问题。

   4.0.0 ru.mycompany myproduct 1.0-SNAPSHOT  UTF-8 1.5.1 1.6 1.6    junit junit 4.10 test   org.easytesting fest-util 1.2.3   org.easytesting fest-assert-core 2.0M8   com.google.guava guava 15.0   org.mockito mockito-all 1.9.5   com.h2database h2 1.3.173   org.powermock powermock-module-junit4 ${powermock.version} test   org.powermock powermock-api-mockito ${powermock.version} test    

这个工作(注意import):

 import static org.easymock.EasyMock.expect; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.powermock.api.easymock.PowerMock.mockStatic; import static org.powermock.api.easymock.PowerMock.replay; @RunWith(PowerMockRunner.class) @PrepareForTest({DriverManager.class, H2Persistence.class}) public class H2PersistenceTest { @Test public void testDropPersonIsCalled() throws SQLException { final Statement statement = mock(Statement.class); final Connection connection = mock(Connection.class); when(connection.createStatement()).thenReturn(statement); mockStatic(DriverManager.class); expect(DriverManager.getConnection(H2Persistence.CONN_TYPE_USER_HOME)) .andReturn(connection); expect(DriverManager.getConnection(null)) .andReturn(null); replay(DriverManager.class); final H2Persistence objectUnderTest = new H2Persistence(); objectUnderTest.open(); verify(statement).executeUpdate("DROP TABLE IF EXISTS PERSON"); verify(statement).executeUpdate(H2Persistence.CREATE_TABLE_PERSON); } } 

执行此操作的常用方法是将连接创建分解为另一个类,并将该实例注入到相关类中。 然后你可以模拟那个新类。

在你的情况下,这样的事情:

 public class H2Persistence implements IPersistence { private final ConnectionFactory connectionFactory; private Connection conn; public H2Persistence(ConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; } @Override public void open() { try { conn = connectionFactory.createConnection(CONN_TYPE_USER_HOME); // etc } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } } public class ConnectionFactory { Connection createConnection(String connType) throws SQLException, ClassNotFoundException { Class.forName("org.h2.Driver"); return DriverManager.getConnection(connType); } } 

在这种特殊情况下,更好的方法是使用标准JDBC接口DataSource而不是您自己的连接工厂类:

 public class H2Persistence implements IPersistence { private final DataSource dataSource; private Connection conn; public H2Persistence(DataSource dataSource) { this.dataSource = dataSource; } @Override public void open() { try { conn = dataSource.getConnection(); // etc } catch (SQLException e) { e.printStackTrace(); } } }