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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34919664/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:32:22  来源:igfitidea点击:

How to mock jdbc connection and resultSet using Mockito in TestNG

javaunit-testingjdbcmockitoresultset

提问by kosmit

I have to write some unit tests but I have problem with mocking ResultSetand jdbc Connection.

我必须编写一些单元测试,但我在模拟ResultSet和 jdbc 方面有问题Connection

I have this method:

我有这个方法:

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

And error is showing in line executeQuery("SELECT name FROM tables")and it sounds like this:

错误显示在队列中executeQuery("SELECT name FROM tables"),听起来像这样:

java.lang.NullPointerException HelperTest.test3(HelperTest.java:71)

Any ideas whats going wrong?

任何想法出了什么问题?

回答by Nick Holt

You need to create an expectationon jdbcConnection.createStatement().

您需要创建一个预期jdbcConnection.createStatement()

By default, I believe a nullis returned.

默认情况下,我相信 anull会返回。

Should read something like:

应该是这样的:

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

回答by Lukas Eder

Mocking the JDBC API on this low level is rather tedious as you should really look into mocking the entirety of the JDBC API. Just a few examples:

在这种低级别模拟 JDBC API 相当乏味,因为您应该真正研究模拟整个 JDBC API。举几个例子:

  • What would happen if anyone called ResultSet.previous()?
  • What would happen if anyone called ResultSet.getObject()rather than getString()?
  • What would happen if the ResultSetwas obtained through Statement.getResultSet()?
  • 如果有人打电话会发生什么ResultSet.previous()
  • 如果有人打电话ResultSet.getObject()而不是会发生什么getString()
  • 如果ResultSet通过 获得会发生什么Statement.getResultSet()

To your client code, it shouldn't matter much if you're calling JDBC one way or another, the result should always be the same. If you really have tomock the database (rather than use e.g. a test database, or better, a testcontainers based approach), then using something like jOOQ's MockDataProvideror MockFileDatabasewould certainly make things much simpler. In your case:

对于您的客户端代码,以一种或另一种方式调用 JDBC 应该没有太大关系,结果应该始终相同。如果您真的必须模拟数据库(而不是使用例如测试数据库,或者更好的基于 testcontainers 的方法),那么使用类似 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);

The above approach will work regardless what the Helper.getTablesName()method does with the passed JDBC Connection.

无论该Helper.getTablesName()方法如何处理传递的 JDBC ,上述方法都将起作用Connection

Note, I'm working for the company behind jOOQ, so this answer is biased.

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