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
How to mock jdbc connection and resultSet using Mockito in TestNG
提问by kosmit
I have to write some unit tests but I have problem with mocking ResultSet
and 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 null
is 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 thangetString()
? - What would happen if the
ResultSet
was obtained throughStatement.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 MockDataProvider
or MockFileDatabase
would certainly make things much simpler. In your case:
对于您的客户端代码,以一种或另一种方式调用 JDBC 应该没有太大关系,结果应该始终相同。如果您真的必须模拟数据库(而不是使用例如测试数据库,或者更好的基于 testcontainers 的方法),那么使用类似 jOOQ 的东西MockDataProvider
或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);
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 背后的公司工作,所以这个答案是有偏见的。