在本地抑制不必要的存根异常

时间:2017-10-27 07:08:29

标签: java mockito

Mockito(从版本2开始)检测到未使用的断条,这通常是一件非常好的事情。

现在考虑以下代码:

result = foo(1) || foo(2); // generally: true if any input is true

和截尾:

when(foo(1)).return(true);
when(foo(2)).return(false);

现在foo(2)被不必要地存根了。但是,对原始代码的最轻微的重构可能会改变(将表达式更改为foo(2) || foo(1))。在这种情况下,如果任何输入为true,我想留下存根以检查结果是true。 (假设短切不是必要的,但可能,当然真正的代码涉及的更多)。

现在我的问题:这样做的优雅方式是什么?优选单个短截线?使用MockitoJUnitRunner.Silent作为跑步者会抑制整个测试类的警告。

2 个答案:

答案 0 :(得分:2)

这个问题的一个迟到的答案:

简而言之,Mockito.lenient() 可用于绕过异常,特别是对于该存根,而不是将 MockitoJUnitRunner.Silent 应用于整个测试类。 不幸的是,API 是在提出这个问题后(将近一年)才推出的。

Mockito.lenient().when(foo(2)).return(false);

但我也建议简化测试方法,这样异常甚至不会出现。

假设你要测试的函数是这样的:

public boolean bar() {
    boolean result = foo(1) || foo(2);
    return result;
}

foo(1)foo(2) 是否返回真/假不是测试 bar() 的问题,而是要测试不同场景的组合,就像这样:

result = a || b;
<头>
一个 b bar() 应该返回
真实 真实 真实
真实 真实
真实 真实

由于短路行为或 OR 操作,通过组合前 2 个案例,它最多可归结为 3 个测试案例(如果您真的想要):

  • bar() 应该在 a 为真时返回真
  • bar() 应在 a 为假且 b 为真时返回真
  • bar() 应在 a 为假且 b 为假时返回假

实施这 3 个测试用例不会给您带来不必要的存根异常。

<块引用>

现在 foo(2) 被不必要地存根了。然而,对原始代码最轻微的重构可能会改变它(将表达式更改为 foo(2) || foo(1))。在这种情况下,如果任何输入为真,我想保留存根以检查结果是否为真。 (假设走捷径不是必须的,但可以,当然真正的代码涉及的要多得多)。

bar()函数(例如result = b || a)上发生任何重构时,不可避免地同时重构测试用例以反映新逻辑,尤其是OR给出的短路效应操作确实导致了 bar() 的不同行为。 如果在逻辑中不期望短路,并且确实实现了在逻辑运行时不会短路,那么 Mockito 将不会引发此类异常,因为 foo(1) 和 {{ 的存根1}} 将是真正需要的。

我想说的是,Mockito 仅根据实现正确地引发异常,建议要么设计测试用例以反映短路逻辑,要么使用 foo(2)

答案 1 :(得分:0)

  

这样做的优雅方式是什么?优选单个短截线?

我认为,当你希望调用其中一个调用时,存在两个不同的调用并不会提供有意义的单元测试。

正如我读到的那样:

Dim Mr As Range
Set Mr = ActiveDocument.Content
With Mr.Find
            .Wrap = wdFindContinue
            .Text = "^p"
            .Replacement.Text = ""
            .Execute Replace:=wdReplaceAll
End With
With Mr.Find
            .Wrap = wdFindContinue
            .Text = "   "
            .Replacement.Text = " "
            .Execute Replace:=wdReplaceAll
End With
With Mr.Find
            .Wrap = wdFindContinue
            .Text = "  "
            .Replacement.Text = " "
            .Execute Replace:=wdReplaceAll
End With

我希望在代码中看到类似的内容:

when(foo(1)).return(true);
when(foo(2)).return(true);

不是:result = foo(1) && foo(2);

在你的情况下,我将对测试的方法进行两次不同的调用(根据它的可读性进行一到两次测试),对于每一次,我只会模拟预期的result = foo(1) || foo(2);调用,而不是两者

  

使用MockitoJUnitRunner.Silent作为跑步者会抑制警告   对于整个测试课程。

就个人而言,我不喜欢隐藏警告,同时可以提高测试代码的质量。

关于MockitoJUnitRunner.Silent,您可以阅读(重点是我的):

  

建议不要使用此版本的跑步者。工程师   应该关心删除未使用的stubbings,因为它们是死代码,   他们添加了不必要的细节,可能会使测试代码变得更难   理解。 如果您有充分的理由使用静音跑步者,请告诉我   我们在邮件列表中知道或在我们的问题跟踪器中提出问题。   另请参见UnacessaryStubbingException