有没有办法修复一个应该 return 由 ResultSet 组成的字符串的测试?
Is there a way to fix a Test which should return a string made of ResultSet?
我有一个从结果集中创建字符串的函数。以及发送消息的那个。你可以在下面看到它们
public String createStringReport(ResultSet resultSet) throws SQLException{
StringBuilder reportData = new StringBuilder("");
int columns = 0;
if(resultSet.getMetaData() != null) {
columns = resultSet.getMetaData().getColumnCount();
while (resultSet.next()) {
for (int i = 1; i <= columns; i++) {
reportData.append(resultSet.getString(i)).append("\t");
}
reportData.append("\n");
}
}
return !reportData.toString().isEmpty() ? reportData.toString() : "No data";
}
private void sendStringReport(String reportData) {
for (User u: users) {
sender.send(u, reportData);
log.info("send report - " + report.getName() + " to" + u.getName());
}
}
我需要编写一个测试,使用之前生成的参数字符串调用发送方。这就是我现在拥有的:
@Test
public void shouldGenerateStringReportWhenThreadRunHasData() throws SQLException {
String result = "somestring";
Report report = getReport(ReportType.STRING);
ReportCreator reportCreator = new
StringReportCreator(report, users, sender, dataSource, unexpectedErrorCounter);
when(resultSet.getString(anyInt())).thenReturn(result);
when(resultSet.next()).thenReturn(true).thenReturn(false);
int columns = 2;
final ResultSetMetaData rsmd = mock(ResultSetMetaData.class);
when(resultSet.getMetaData()).thenReturn(rsmd);
doReturn(rsmd).when(resultSet).getMetaData();
StringBuilder reportData = new StringBuilder("");
if(resultSet.getMetaData() != null) {
while (resultSet.next()) {
for (int i = 1; i <= columns; i++) {
reportData.append(result).append("\t");
}
reportData.append("\n");
}
}
reportCreator.run();
verify(sender, Mockito.times(users.size())).send(any(User.class), eq(reportData.toString));
}
不幸的是,有人告诉我:
Argument(s) are different! Wanted:
telegramSender.send(
<any reportbot.entity.User>,
"somestring somestring
somestring somestring
"
);
-> at ru.phoenixdnr.reportbot.ReportCreatorTest$Run.shouldGenerateStringReportWhenThreadRunHasData(ReportCreatorTest.java:233)
Actual invocations have different arguments:
telegramSender.send(
User(id=1, idTelegram=2, name=892e0f69-c10e-4961-b22e-11de333fbb55, email=73507828-9c7a-4026-8599-5e6c8c62e3c7),
"No data"
);
为什么报告数据是空的?
我怎样才能解决这个问题?我已经尝试了一个星期了,但没有任何帮助。
您错过了对 ResultSetMetadata
的 getColumnCount
电话的嘲笑:
when(rsmd.getColumnCount()).thenReturn(2);
问题似乎是您:
- 设置模拟结果集,
- 在构建预期输出时从中读取结果,
- 调用您尝试测试的方法,具有相同的结果集。
被测方法运行时,发现结果集已经耗尽(或者至少.next()
returnsfalse
),所以没有更多的数据从中读取。因此你得不到任何数据。
如果生成预期文本的代码使用单独的结果集,则不会出现此问题。
解决此问题的一种方法是将所有 ResultSet
模拟设置代码移动到一个单独的方法中,该方法创建并 return 模拟 ResultSet
。这样您就可以调用此方法两次以获得两个不同的模拟 ResultSet
,一个用于创建结果集以用于创建预期结果,一次用于传递给报告创建者。
另一个修复方法是在不使用模拟 ResultSet
的情况下生成预期的输出。你知道 ResultSet.getMetaData()
不会 return null
,所以空检查是不必要的,你也知道模拟 ResultSet
中有多少行,所以你可以用 for
循环替换 while
循环。
我有一个从结果集中创建字符串的函数。以及发送消息的那个。你可以在下面看到它们
public String createStringReport(ResultSet resultSet) throws SQLException{
StringBuilder reportData = new StringBuilder("");
int columns = 0;
if(resultSet.getMetaData() != null) {
columns = resultSet.getMetaData().getColumnCount();
while (resultSet.next()) {
for (int i = 1; i <= columns; i++) {
reportData.append(resultSet.getString(i)).append("\t");
}
reportData.append("\n");
}
}
return !reportData.toString().isEmpty() ? reportData.toString() : "No data";
}
private void sendStringReport(String reportData) {
for (User u: users) {
sender.send(u, reportData);
log.info("send report - " + report.getName() + " to" + u.getName());
}
}
我需要编写一个测试,使用之前生成的参数字符串调用发送方。这就是我现在拥有的:
@Test
public void shouldGenerateStringReportWhenThreadRunHasData() throws SQLException {
String result = "somestring";
Report report = getReport(ReportType.STRING);
ReportCreator reportCreator = new
StringReportCreator(report, users, sender, dataSource, unexpectedErrorCounter);
when(resultSet.getString(anyInt())).thenReturn(result);
when(resultSet.next()).thenReturn(true).thenReturn(false);
int columns = 2;
final ResultSetMetaData rsmd = mock(ResultSetMetaData.class);
when(resultSet.getMetaData()).thenReturn(rsmd);
doReturn(rsmd).when(resultSet).getMetaData();
StringBuilder reportData = new StringBuilder("");
if(resultSet.getMetaData() != null) {
while (resultSet.next()) {
for (int i = 1; i <= columns; i++) {
reportData.append(result).append("\t");
}
reportData.append("\n");
}
}
reportCreator.run();
verify(sender, Mockito.times(users.size())).send(any(User.class), eq(reportData.toString));
}
不幸的是,有人告诉我:
Argument(s) are different! Wanted:
telegramSender.send(
<any reportbot.entity.User>,
"somestring somestring
somestring somestring
"
);
-> at ru.phoenixdnr.reportbot.ReportCreatorTest$Run.shouldGenerateStringReportWhenThreadRunHasData(ReportCreatorTest.java:233)
Actual invocations have different arguments:
telegramSender.send(
User(id=1, idTelegram=2, name=892e0f69-c10e-4961-b22e-11de333fbb55, email=73507828-9c7a-4026-8599-5e6c8c62e3c7),
"No data"
);
为什么报告数据是空的? 我怎样才能解决这个问题?我已经尝试了一个星期了,但没有任何帮助。
您错过了对 ResultSetMetadata
的 getColumnCount
电话的嘲笑:
when(rsmd.getColumnCount()).thenReturn(2);
问题似乎是您:
- 设置模拟结果集,
- 在构建预期输出时从中读取结果,
- 调用您尝试测试的方法,具有相同的结果集。
被测方法运行时,发现结果集已经耗尽(或者至少.next()
returnsfalse
),所以没有更多的数据从中读取。因此你得不到任何数据。
如果生成预期文本的代码使用单独的结果集,则不会出现此问题。
解决此问题的一种方法是将所有 ResultSet
模拟设置代码移动到一个单独的方法中,该方法创建并 return 模拟 ResultSet
。这样您就可以调用此方法两次以获得两个不同的模拟 ResultSet
,一个用于创建结果集以用于创建预期结果,一次用于传递给报告创建者。
另一个修复方法是在不使用模拟 ResultSet
的情况下生成预期的输出。你知道 ResultSet.getMetaData()
不会 return null
,所以空检查是不必要的,你也知道模拟 ResultSet
中有多少行,所以你可以用 for
循环替换 while
循环。