如何在 TestNG 中使用 Mockito 模拟 jdbc 连接和结果集
How to mock jdbc connection and resultSet using Mockito in TestNG
我必须编写一些单元测试,但我在模拟 ResultSet
和 jdbc Connection
时遇到问题。
我有这个方法:
@Test
public void test3() throws SQLException, IOException {
Connection jdbcConnection = Mockito.mock(Connection.class);
ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");
Mockito.when(jdbcConnection
.createStatement()
.executeQuery("SELECT name FROM tables"))
.thenReturn(resultSet);
//when
List<String> nameOfTablesList = null;
try {
nameOfTablesList = Helper.getTablesName(jdbcConnection);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//then
Assert.assertEquals(nameOfTablesList.size(), 3);
}
第 executeQuery("SELECT name FROM tables")
行显示错误,听起来像这样:
java.lang.NullPointerException HelperTest.test3(HelperTest.java:71)
有什么问题吗?
您需要在 jdbcConnection.createStatement()
上创建一个 预期 。
默认情况下,我相信会返回 null
。
应该这样读:
ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");
Statement statement = Mockito.mock(Statement.class);
Mockito.when(statement.executeQuery("SELECT name FROM tables")).thenReturn(resultSet);
Connection jdbcConnection = Mockito.mock(Connection.class);
Mockito.when(jdbcConnection.createStatement()).thenReturn(statement);
在这个低级别上模拟 JDBC API 相当乏味,因为您真的应该考虑模拟整个 JDBC API。举几个例子:
- 如果有人打电话给
ResultSet.previous()
会怎样?
- 如果有人打电话给
ResultSet.getObject()
而不是 getString()
会怎样?
- 如果
ResultSet
是通过Statement.getResultSet()
获得的会怎样?
对于您的客户端代码,无论您以何种方式调用 JDBC 都不重要,结果应该始终相同。如果你真的 必须 模拟数据库(而不是使用例如测试数据库,或者更好,testcontainers based approach), then using something like jOOQ's MockDataProvider
or MockFileDatabase
肯定会让事情变得更简单。在你的情况下:
MockDataProvider db = new MockFileDatabase(
"SELECT name FROM tables;\n"
+ "> name\n"
+ "> --------\n"
+ "> table_r3\n"
+ "> table_r1\n"
+ "> table_r2\n"
+ "> @rows: 3\n");
//when
List<String> nameOfTablesList = null;
try {
nameOfTablesList = Helper.getTablesName(new MockConnection(db));
} catch (SQLException e) {
e.printStackTrace();
}
//then
Assert.assertEquals(nameOfTablesList.size(), 3);
无论 Helper.getTablesName()
方法如何处理传递的 JDBC Connection
.
,上述方法都有效
注意,我在 jOOQ 背后的公司工作,所以这个答案有偏见。
我必须编写一些单元测试,但我在模拟 ResultSet
和 jdbc Connection
时遇到问题。
我有这个方法:
@Test
public void test3() throws SQLException, IOException {
Connection jdbcConnection = Mockito.mock(Connection.class);
ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");
Mockito.when(jdbcConnection
.createStatement()
.executeQuery("SELECT name FROM tables"))
.thenReturn(resultSet);
//when
List<String> nameOfTablesList = null;
try {
nameOfTablesList = Helper.getTablesName(jdbcConnection);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//then
Assert.assertEquals(nameOfTablesList.size(), 3);
}
第 executeQuery("SELECT name FROM tables")
行显示错误,听起来像这样:
java.lang.NullPointerException HelperTest.test3(HelperTest.java:71)
有什么问题吗?
您需要在 jdbcConnection.createStatement()
上创建一个 预期 。
默认情况下,我相信会返回 null
。
应该这样读:
ResultSet resultSet = Mockito.mock(ResultSet.class);
Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
Mockito.when(resultSet.getString(1)).thenReturn("table_r3").thenReturn("table_r1").thenReturn("table_r2");
Statement statement = Mockito.mock(Statement.class);
Mockito.when(statement.executeQuery("SELECT name FROM tables")).thenReturn(resultSet);
Connection jdbcConnection = Mockito.mock(Connection.class);
Mockito.when(jdbcConnection.createStatement()).thenReturn(statement);
在这个低级别上模拟 JDBC API 相当乏味,因为您真的应该考虑模拟整个 JDBC API。举几个例子:
- 如果有人打电话给
ResultSet.previous()
会怎样? - 如果有人打电话给
ResultSet.getObject()
而不是getString()
会怎样? - 如果
ResultSet
是通过Statement.getResultSet()
获得的会怎样?
对于您的客户端代码,无论您以何种方式调用 JDBC 都不重要,结果应该始终相同。如果你真的 必须 模拟数据库(而不是使用例如测试数据库,或者更好,testcontainers based approach), then using something like jOOQ's MockDataProvider
or MockFileDatabase
肯定会让事情变得更简单。在你的情况下:
MockDataProvider db = new MockFileDatabase(
"SELECT name FROM tables;\n"
+ "> name\n"
+ "> --------\n"
+ "> table_r3\n"
+ "> table_r1\n"
+ "> table_r2\n"
+ "> @rows: 3\n");
//when
List<String> nameOfTablesList = null;
try {
nameOfTablesList = Helper.getTablesName(new MockConnection(db));
} catch (SQLException e) {
e.printStackTrace();
}
//then
Assert.assertEquals(nameOfTablesList.size(), 3);
无论 Helper.getTablesName()
方法如何处理传递的 JDBC Connection
.
注意,我在 jOOQ 背后的公司工作,所以这个答案有偏见。