隔离框架(Moq,RhinoMock等)会导致测试过度指定吗?

时间:2010-05-10 07:54:40

标签: unit-testing tdd

在Osherove的伟大着作“单元测试的艺术”中,测试反模式之一是过度规范,这与测试对象的内部状态而不是某些预期输出基本相同。根据我的经验,使用隔离框架可能会导致与测试内部行为相同的不良副作用,因为人们往往只实现使存根与被测对象交互所必需的行为。现在,如果您的实现稍后更改(但合同保持不变),您的测试将突然中断,因为您期望存根中的某些数据未实现。

那么您认为解决这个问题的最佳方法是什么?

1)完全实现您的存根/模拟,这会产生负面的副作用,可能会使您的测试更具可读性,并且还指定了使测试通过的必要性。

2)赞成手动,完全实现的假货。

3)实现你的存根/假货,这样它们就可以让你的测试通过,然后处理这可能带来的脆弱性。

3 个答案:

答案 0 :(得分:3)

我不认为您应该支持手动测试 - 除非您更喜欢测试而不是代码。

相反,您有另一种选择 - 如果您测试功能而不是实现,请尝试避免测试私有方法(可以重构),并且通常编写不那么脆弱的测试,您将看到使用模拟/隔离框架不要求您过度指定系统,也不会导致测试变得更脆弱。

简而言之 - 编写脆弱的测试可以在有或没有假货/模拟的情况下完成,反之亦然。

答案 1 :(得分:1)

我倾向于使用模拟而不是存根/假对象。我发现它们的麻烦要少得多,而且它们在控制测试代码方面做得更好,因为它不会被各种半生不熟的实现混乱。它们还有助于澄清正在测试的内容。

另一个优点是我只需要解决被测试的类需要模拟特定内容的地方。因此,我不必编码不重要的地方。至于验证,我只需要从被测试的类到我关心的模拟调用,并考虑测试的重要方面。

答案 2 :(得分:0)

我认为,问题总是一样的,虽然它有不同的风格:如果你的测试以某种方式覆盖了类的内部,那么你将打破覆盖这个内部代码的测试。

恕我直言,有两种方法可以解决这个问题:

  1. 您的测试仅涵盖班级的公共合同 - 一种广泛采用的测试策略,原因如下:只要公共合同保持不变,您就不必更改测试。不幸的是,这不是,在进行测试驱动开发时将会有什么。
  2. 如果您的测试来自TDD流程,那么他们将定期涵盖非公开代码。这意味着如果更改代码,它们将会中断。保持事物同步的唯一方法是将测试与代码一起“修复”。这意味着在开发期间需要更多维没有什么方法可以轻松应对(除了扔掉测试,当然......)。
  3. 我个人的'出路'是用'代码元素'来思考而不仅仅是代码。代码元素由三部分组成:文档,测试,代码。因此,如果您更改元素的一部分,您还必须调整其他两个元素 - 否则您将留下一个损坏的代码元素。