如何在TestNG中使用Mockito模拟jdbc连接和结果集

2022-09-03 00:38:17

我必须编写一些单元测试,但我有模拟和jdbc的问题。ResultSetConnection

我有这个方法:

@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)

任何想法出了什么问题?


答案 1

您需要对 创建期望jdbcConnection.createStatement()

默认情况下,我认为返回 a。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);

答案 2

在这个低级别上模拟JDBC API是相当乏味的,因为你应该真正考虑模拟整个JDBC API。举几个例子:

  • 如果有人打电话,会发生什么?ResultSet.previous()
  • 如果有人打电话而不是打电话,会发生什么?ResultSet.getObject()getString()
  • 如果通过以下方式获得,会发生什么情况?ResultSetStatement.getResultSet()

对于您的客户端代码,如果您以某种方式调用JDBC,则结果应该始终相同。如果你真的必须模拟数据库(而不是使用例如测试数据库,或者更好的是基于测试容器的方法),那么使用像jOOQ的MockDataProviderMockFileDatabase这样的东西肯定会让事情变得简单得多。在您的情况下:

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);

无论该方法对传递的JDBC做什么,上述方法都将起作用。Helper.getTablesName()Connection

请注意,我为jOOQ背后的公司工作,所以这个答案是有偏见的。


推荐