【问题标题】:How to mock ResultSet.next() method using Mockito如何使用 Mockito 模拟 ResultSet.next() 方法
【发布时间】:2015-08-19 06:32:50
【问题描述】:

我这样嘲讽java.sql.ResultSet

ResultSet rs = mock(ResultSet.class);
when(rs.next()).thenReturn(true); // this seems wrong appraoch

测试代码是这样的

while (rs.next()) {
  // doing stuff here
}

所以问题是当我模拟 rs.next()true 然后 while 循环永远不会终止。我想在 2 次迭代后终止 while 循环。那么我该如何模拟rs.next() 方法呢?

我也试过了

when(rs.next()).thenReturn(true, true, false); // always return false 

请帮忙!

【问题讨论】:

    标签: java unit-testing mockito


    【解决方案1】:

    您可以链接doReturn() 方法调用:

    doReturn(true).doReturn(true).doReturn(false).when(rs).next();
    

    或者,如 cmets 中所述,链接 thenReturn 方法调用:

    when(rs.next()).thenReturn(true).thenReturn(true).thenReturn(false);
    

    或者,如果您想更进一步,可以使用 Mockito Answers:

    when(rs.next()).thenAnswer(new Answer() {
        private int iterations = 2;
    
        Object answer(InvocationOnMock invocation) {
            return iterations-- > 0;
        }
    });
    

    【讨论】:

    • 也可以链thenReturn:when(rs.next()).thenReturn(true).thenReturn(false)
    • 您的两种方法的行为与:when(rs.next()).thenReturn(true, true, false);这是行不通的情况:(
    • 它总是取最后一个值作为结果 thenReturn ?
    • 刚刚使用 Mockito 1.10.19 在本地测试。我的代码按预期工作。
    • 好的,从技术上讲,您的代码对我来说也不错,但我在告诉一些人我可能遗漏了什么并且无法弄清楚:(
    【解决方案2】:

    试试

    when(rs.next()).thenReturn(true).thenReturn(true).thenReturn(false);
    

    【讨论】:

    • 我每次都在 rs.next() 上得到错误 :( 无效
    • 适用于我的 Mockito 2.0.2 beta。如果您仍然卡住,也许您应该编辑您的问题以附加完整的测试以及您尝试的修复,并提及 Mockito 的版本以防有人知道错误。
    • 我在不同的测试中使用了你的方法,它工作正常,但在这个特定的场景中它没有。我想我错过了一些东西!不知道是什么:(
    【解决方案3】:

    虽然其他答案在技术上是正确的(如果在您的代码中不起作用,那么可能还有其他问题在起作用,需要更多代码)。他们都错过了一个关键点:

    您不应模拟 JDBC 类,而应创建一个带有真实数据库的集成测试。还要注意ResultSet 确实是一个接口,但驱动程序/数据库可能在行为上有一些差异。这种模拟这些的测试使开发人员对真实的生产行为视而不见。

    如果这段代码只是处理返回的数据而不是实际的 JDBC 调用代码,那么这段代码应该与 JDBC 类分离,因为不应导入 ResultSet。从长远来看,它有助于将技术代码与业务代码分开。

    【讨论】:

    • 嗯,我认为你是对的。我使用了 mockrunner lib 的 MockResultSet。它工作正常,但我不能用它做其他主要的事情。
    • 我并不反对集成测试的必要性,但说您需要针对此类案例进行集成测试,这太过分了。如果返回不同数量的结果(例如,如果返回多个记录,则抛出异常),完全有可能期望较低级别的 DAO 类型代码表现不同。使用单元测试测试该行为是完全有意义的。
    • @RobbyCornelissen 是的,当然总有一些很好的理由不遵循这些指导方针,但这通常是非常狭窄的案例;这似乎不是这里的一个。无论如何,即使对于您提到的情况,实现者或不同版本也可能会以不同的方式和意想不到的方式失败,具体取决于适当的条件。测试这样的条件可能真的很有挑战性,在这里额外的模拟后面有一个 DB 可能会给人一种错误的安全感。外部系统的正确和安全测试比我们想象的要困难得多,而且模拟很少是其中的一部分。
    【解决方案4】:
    when(rs.next()).thenReturn(true, true, false);
    

    这应该可以。

    我从 'mockito-core:1.10.19' 的 javadoc 中找到一个示例。

    看看这个: org.mockito.Mockito.when

    【讨论】:

      猜你喜欢
      • 2020-12-08
      • 2020-03-20
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      相关资源
      最近更新 更多