【问题标题】:Mocking only partial of the test仅模拟部分测试
【发布时间】:2013-12-07 09:36:00
【问题描述】:

我正在测试一种方法,如果传递给该方法的参数超出某些业务规则限制,该方法几乎会立即抛出异常。

我测试的类有依赖关系,所以我模拟它们。但是,由于几乎立即抛出异常,我是否允许(是否正确)只模拟我需要的东西?还是我需要指定整个测试?

我希望抛出异常,所以我需要模拟所有对象并设置返回值等吗?

在这些情况下什么是正确的?在同一个测试中同时进行验证和断言是错误的吗?

【问题讨论】:

  • 务实:测试是否检查是否在应该抛出异常时抛出异常,如果方法未抛出此异常,是否会失败?是的,所以没关系。您的测试是否以相同的方法进行断言和验证有用且可读?是的,所以没关系。
  • @JBNizet 谢谢。我就是这么想的。

标签: java unit-testing mocking mockito


【解决方案1】:

如果您可以提供一些代码示例,那就太好了。但是,正如我理解你的问题,你是Unit Testing 一个方法,它会在检查某种业务规则后立即抛出异常。您还向此类(SUT - 被测系统)注入了依赖项。这些依赖项在您的单元测试中被模拟/存根,但是由于立即抛出异常,您不确定模拟所有内容是否是一个好主意。

通常,对于任何单元测试,您都希望绝对确定您的单元测试只包含它需要的内容,而不包含其他内容。如果您在单元测试中模拟存根的东西,并且在您的 SUT 中的测试执行期间没有使用它们,那么

一个。您的测试可能更难维护,也更难阅读,因为可能不容易弄清楚测试真正使用了什么以及测试实际在做什么。

b.您的测试可能因错误原因而失败。例如,您的 SUT 完全按照您期望的方式工作,但是由于不需要的依赖项被模拟,任何重构和错误的原因导致您的测试失败。这也称为false positive 测试。

您应该尝试实现的是编写一个单独的单元测试来验证异常场景。此测试只会注入依赖项以使您的规则违反,因此您可以测试异常情况。您的所有其他测试都会相应地注入依赖项,以使这些测试尽可能满足。

【讨论】:

  • 我实际上不同意。世界不是非黑即白,但在我看来,这种方法太接近白盒测试了。在编写单元测试时,我们正在检查方法的行为——它是否履行合同。在方法开始时抛出异常的事实对测试应该没有意义。当有人将重构方法将异常移到末尾时,您所说的因错误原因而失败实际上会适用,这可能会由于不满足的依赖关系而导致测试失败。我所做的总是提供所有依赖项。
  • 你可能误解了我的回答。这不仅是“将异常移动”到最后导致它失败,而且是语义违规导致测试失败。对特定单元测试的较小依赖性始终是规范,也是标准。这是你的意见,我很感激。
【解决方案2】:

我想这个问题没有最终答案,但正如我在 Spocks 答案的评论中所说,我所做的始终是提供被测类所需的所有依赖项,无论特定测试将使用什么它与否。这就是我这样做的原因:

基本上,实现可能会改变,但如果满足预期的行为,我的测试仍然应该通过。请注意,不使用依赖项可能是明确的预期行为。在这种情况下,我认为可以省略。

至少在使用 TDD 时(您应该先编写测试),当您编写测试时,您不知道何时会引发异常。除非您对此没有明确的行为要求,否则从测试的角度来看,这应该是完全透明的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 2017-03-01
    • 2012-06-17
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    相关资源
    最近更新 更多