在JUnit测试中模拟对象 - 最佳实践?

时间:2011-05-04 08:52:32

标签: java junit mocking

您认为JUnit测试中的模拟对象是最佳实践吗?我没有看到巨大的优势。当然,如果你有一个不应该在你的测试中考虑的数据库它是有道理的,但为什么不只是注入该组件的其他实现(如果使用spring)。测试的对象工厂将使这很容易。我没有太多经验(我们正在使用Mockito),但我已经看到,应用程序代码被修改,以便某些属性变得可模糊!在我的意见中,测试用例永远不应该在生产代码中改变这种变化。

那你觉得这个话题怎么样?你在哪些情况下嘲笑你的对象或为什么不嘲笑你?

4 个答案:

答案 0 :(得分:18)

嘲笑的想法是你完全孤立你正在测试的东西。然后,当测试失败时,您可以确定问题出在哪里,而无需查看整个类依赖关系树。如果您正在测试多个类的行为,那么这不是真正的单元测试。

测试的对象工厂可能会使用stubbed方法创建对象,而mocking框架本质上是用于测试的通用对象工厂。但是模拟提供了比存根更多的功能 - 这是Martin Fowler在这里详细介绍的一个区别:http://martinfowler.com/articles/mocksArentStubs.html

如果你觉得嘲讽很艰难,而且你也发现你做了很多,那么这就是TDD的经典例子,告诉你你的设计可以改进。

答案 1 :(得分:12)

  

我已经看过那个应用程序了   代码被修改,以便一些   属性变得模糊!测试用例   永远不应该改变这种变化   我的意见中的生产性代码。

TDD的核心理念是强迫您使所有代码都可测试,一般来说设计会变得更好。这并不一定意味着只是让所有东西都可以模仿,它也可能意味着减少耦合,这样就不需要更少的嘲弄。

即使您不同意这一理念(我不是100%自己购买),只要您认为自动化测试可以提供价值,那么更改生产代码以支持该值是有道理的(除非它以某种其他方式严重损害设计。)

答案 2 :(得分:4)

  • 定义校准类接口(接口发现
  • 允许从上到下的设计
  • 隔离(单元测试)
  • 澄清类之间的相互作用
  • 有时候只能看到对象是否符合您的要求(Mocks and Tell Don’t Ask
  • 鼓励更好的结构化测试。例如,jukito自动注入模拟,使您可以专注于您想要测试的内容。
  • 允许保留封装
  • 减少依赖

  • 不应该嘲笑价值对象

从必要性模拟框架grow-out。正如马修吉利亚德所说,如果有某种嘲弄正在进行,那么这表明设计可以改进或缺乏测试重点。测试揭示了代码中的许多问题。

  

但为什么不只是注入该组件的其他实现(如果使用spring)。

你必须编写实现。使用模拟框架就可以完成。

  

我已经看到,应用程序代码被修改,以便某些属性变得可模糊!在我看来,测试用例绝不应该在生产代码中做出这样的改变。

如果 mockable 意味着可测试,那么它是另一种方式。例如,在TDD测试中定义生产代码。

答案 3 :(得分:1)

我认为真正的问题是单元测试是否是最佳实践。如果你相信它,那么使用 mocking 是必要的,从测试单元与其依赖项的实现隔离开来。

但是,这与 testability 的概念有何混淆。复杂,复杂的代码本质上是不可测试的,因为它很难理解。具有简洁设计的良好代码通常更易于理解和维护;那为什么要进行单元测试呢?

混淆源于某些模拟工具中发现的某些任意限制,例如无法模拟finalstatic方法,或需要让测试单元直接使用模拟对象在测试代码中创建。其他模拟工具没有这些限制,因此不要求“应用程序代码被修改,以便某些属性变得可模糊”。使用现代编程语言/平台(Java,C#,Python,Ruby等)一切都是可以模仿的;这只是在模拟API中暴露这种力量的问题,并且已经针对每种语言进行了操作(为了完全公开,我开发了一种这样的工具)。