【问题标题】:Mockito - verify a double valueMockito - 验证双重值
【发布时间】:2013-05-02 10:16:44
【问题描述】:

我有一个名为 method1 的方法,它接受一个在 myManager 上调用的 double 我正在传入这个 65.888 * 60。当我尝试验证这一点时,我遇到了浮点问题。验证失败。它预计 3953.28 但 3953.280029296875

verify(myManager, times(1)).method1(65.888 * 60d);

无论如何我可以让这个验证对浮点检查进行模糊检查。就像你对 assertEquals 所做的一样,你在最后输入一个增量。

谢谢

【问题讨论】:

  • 不确定,但正如 api 中所述,verify 不会检查结果。验证只做:验证某些行为发生过一次。那么您要比较实际值和预期值的代码在哪里?
  • 进行比较的是mockito。它正在验证该方法是用 x 调用的,但它正在接收 y(由于浮点问题)。验证在 mockito 代码中的某处完成
  • 你能提供整个测试用例吗?因为,通常有很强的区别。您断言一个值(测试状态)并验证调用是否发生(测试交互)。你也可以写verify(myManager, times(1)).method1(anyDouble());

标签: java unit-testing mockito


【解决方案1】:

您可以捕获价值,例如

final ArgumentCaptor<Double> captor = ArgumentCaptor.forClass(Double.class)
...
verify(myManager).method1(captor.capture());

然后断言:

assertEquals(expected, captor.getValue(), delta)

或者,也许,使用执行断言的参数匹配器:

verify(myManager).method1(doubleThat(new ArgumentMatcher<Double>() 
{
    @Override 
    public boolean matches(final Object actual)
    {
        return Math.abs(expected - (Double) actual) <= delta;
    }
}));

更新:

您可以使用AdditionalMatchers.eq(double, double) 代替上述任何一种方法,例如:

verify(myManager).method1(AdditionalMatchers.eq(expected, delta));

尽管根据文档明智地使用 AdditonalMatchers 匹配器:

AdditionalMatchers 提供了很少使用的匹配器,只是为了与 EasyMock 兼容。非常明智地使用额外的匹配器,因为它们可能会影响测试的可读性。建议使用 Matchers 中的匹配器,并保持 stubbing 和验证简单。

【讨论】:

  • 感谢@Jonathan。我的实际代码有点复杂,因为该方法实际上也需要一个字符串参数。使用 doubleThat 我现在必须为每个参数使用 ArgumentMatchers,这很痛苦。它虽然有效,但谢谢! +1
  • 我不明白为什么不推荐使用AdditonalMatchers。第二种方式实际上更具可读性,那么阻止人们使用它的意义何在
  • 我认为AdditionalMatchers.eq(expected, delta) 应该在标准浮点等于上使用。直接比较 doublefloat 几乎不是一个好主意。甚至 JUnitassertEquals(expected,value) 也被弃用,取而代之的是使用 delta 值的比较方法。
【解决方案2】:

有一个 Hamcrest 匹配器非常适合。

org.hamcrest.Matchers.closeTo(value, error)

所以你可以写类似的东西

verify(myManager).method1(doubleThat(org.hamcrest.Matchers.closeTo(65.888 * 60, 0.001)));

顺便说一句,您永远不需要在 Mockito verify 中写入 times(1),因为这是 Mockito 为您提供的 verify 的默认类型。

【讨论】:

    【解决方案3】:

    以下代码对我有用:

    private class MockedClass {
        public void method1(double d) {}
    }
    
    @Test
    public final void testMockito() {
        MockedClass d = mock(MockedClass.class);
        d.method1(3953.28);
        verify(d, times(1)).method1(65.888 * 60d);
    }
    

    也许您应该改为使用 anyDouble() 调用该方法或使用以下匹配器:http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/number/IsCloseTo.html

    【讨论】:

      【解决方案4】:

      如何使用:

      when(65.888).thenReturn(65.888 * 60);
      
      assertEquals(65.888 * 60, new BigDecimal(Double.toString(65.888 * 60))
          .setScale(pRoundingDecimalPlaces, 2).doubleValue());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-05
        • 1970-01-01
        • 2010-11-11
        • 2014-04-01
        • 2015-07-16
        • 1970-01-01
        • 1970-01-01
        • 2017-03-12
        相关资源
        最近更新 更多