【问题标题】:Java Mock throw an exception, then return a value?Java Mock 抛出异常,然后返回值?
【发布时间】:2017-08-09 17:25:07
【问题描述】:

我正在使用 JUnit 4 和 Mockito 2。我正在尝试模拟一种情况,即模拟函数在第一次调用时返回异常,而在随后的调用中返回一个有效值。我尝试简单地使用thenThrow(),后跟thenReturn(),但这显然不是正确的方法

when(stmt.executeUpdate()).thenThrow(new SQLException("I have failed."));
when(stmt.executeUpdate()).thenReturn(1);
sut.updateValue("1");
verify(dbc).rollback();
sut.updateValue("2");
verify(dbc).commit();

然而,这两个调用都会导致调用 rollback(),它位于 catch 语句中。

【问题讨论】:

    标签: java unit-testing mockito


    【解决方案1】:

    最简单的方法是这样的:

    when(stmt.executeUpdate())
         .thenThrow(new SQLException("I have failed."))
         .thenReturn(1);
    

    但是单元测试中的单一方法应该验证关于代码行为的单一期望。因此,更好的方法是编写两个独立的测试方法。

    【讨论】:

    • 如果有人想知道,您可能想要这样的原因是您正在测试的方法是否多次调用模拟方法。然后你需要这样的东西来控制执行。
    【解决方案2】:

    thenAnswer() 与带有某种状态的自定义Answer 一起使用,例如:

    class CustomAnswer extends Answer<Integer> {
    
        private boolean first = true;
    
        @Override
        public Integer answer(InvocationOnMock invocation) {
            if (first) {
                first = false;
                throw new SQLException("I have failed.");
            }
            return 1;
        }
    }
    

    一些阅读:https://akcasoy.wordpress.com/2015/04/09/the-power-of-thenanswer/(注意:不是我的博客)

    【讨论】:

      【解决方案3】:

      您可以进行两个单独的测试。 要验证异常,您可以执行以下操作:

      @Test(expected = SQLException.class)
      public void yourTest()throws Exception{
      stmt.executeUpdate(); //set your logic to produce the exception
      }
      

      然后再做一次成功场景的测试

      【讨论】:

      • 这不是被要求的 - 模拟方法需要在第一次调用时失败,然后返回一个值
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-10
      • 2010-12-05
      • 2013-05-29
      • 2012-12-22
      • 2012-06-08
      相关资源
      最近更新 更多