Unit testing 如何使用模拟?

Unit testing 如何使用模拟?,unit-testing,mocking,Unit Testing,Mocking,当我最初被介绍到模拟时,我觉得主要目的是模拟来自外部数据源的对象。这样,我就不必维护一个自动化的单元测试数据库,我可以伪造它 但现在我开始有了不同的想法。我想知道mock是否能更有效地将测试方法与自身之外的任何东西完全隔离开来。不断浮现在脑海中的图像是你在绘画时使用的背景。你不想让油漆到处都是。我只是在测试那个方法,我只想知道它对这些伪造的外部因素有什么反应 这样做似乎令人难以置信地乏味,但我看到的好处是,当测试失败时,这是因为它是错误的,而不是16层。但现在我必须进行16次测试才能获得相同的测

当我最初被介绍到模拟时,我觉得主要目的是模拟来自外部数据源的对象。这样,我就不必维护一个自动化的单元测试数据库,我可以伪造它

但现在我开始有了不同的想法。我想知道mock是否能更有效地将测试方法与自身之外的任何东西完全隔离开来。不断浮现在脑海中的图像是你在绘画时使用的背景。你不想让油漆到处都是。我只是在测试那个方法,我只想知道它对这些伪造的外部因素有什么反应

这样做似乎令人难以置信地乏味,但我看到的好处是,当测试失败时,这是因为它是错误的,而不是16层。但现在我必须进行16次测试才能获得相同的测试覆盖率,因为每一件产品都要单独测试。此外,每项测试都变得更加复杂,与测试方法的联系也更加紧密


我觉得这是对的,但也很残酷,所以我想知道别人怎么想。

是的,我同意。我认为嘲弄有时是痛苦的,但通常是必要的,这样你的测试才能真正成为单元测试,也就是说,只有你能让你的测试关注的最小单元在测试中。这允许您消除可能影响测试结果的任何其他因素。您最终会得到更多的小测试,但要找出代码的问题所在就变得容易多了。

不要走黑暗的道路(大师卢克):)不要嘲笑一切。你可以,但你不应该。。。原因如下

  • 如果你继续孤立地测试每一种方法,当你把它们结合在一起时,你会有惊喜,也会有特别的工作。我们构建对象,以便它们能够共同解决更大的问题。。它们本身是微不足道的。您需要知道所有合作者是否都按预期工作
  • mock通过引入复制使测试变得脆弱-是的,我知道这听起来令人担忧。对于您设置的每个mock expect,有n个地方存在您的方法签名。实际代码和模拟预期(在多个测试中)。更改实际代码更容易。。。更新所有的模拟期望是乏味的
  • 您的测试现在可以了解内部实施信息。因此,您的测试取决于您选择如何实现解决方案。。。糟糕。测试应该是一个可以由多个解决方案满足的独立规范。我应该可以自由地在代码块上按delete键并重新实现,而不必重写测试套件。。因为需求仍然保持不变
最后,如果感觉不对,我会说“如果它像鸭子一样呱呱叫,像鸭子一样走路,那么它可能就是鸭子”。。可能是的*使用模拟来抽象出问题子对象,如IO操作、数据库、第三方组件等。。就像盐一样,有些是必需的。。太多和:x*
这是基于国家的测试与基于实践的测试之间的圣战。。谷歌搜索会给你更深的洞察力

澄清:我在这里进行了一些阻力w.r.t.集成测试:)为了澄清我的立场

  • 模拟不在“验收测试”或集成领域中。您只能在单元测试世界中找到它们。。这就是我的重点
  • 验收测试是不同的,非常需要,而不是贬低它们。但是单元测试和验收测试是不同的,应该保持不同
  • 组件或包中的所有协作者不需要彼此隔离。。就像是过度的微观优化。它们的存在是为了一起解决问题。。凝聚力
我的理念是,您应该编写可测试代码以适应测试,
不编写适合代码的测试

至于复杂性,我的观点是,测试应该简单易写,因为如果需要,您可以编写更多的测试

我可能同意,如果您正在模拟的类没有测试套件,那么这可能是一个好主意,因为如果它们确实有一个适当的测试套件,您将知道在没有隔离的情况下问题在哪里


我使用模拟对象的大部分时间是在我编写测试的代码紧密耦合(读:糟糕的设计)的情况下,当它们所依赖的类不可用时,我不得不编写模拟对象。当然,mock对象有一些有效的用法,但是如果您的代码需要它们的用法,我会再看一看设计。

我建议您看看Martin Fowler的文章,以获得比我能给您的更权威的mock处理方法

mock的目的是在独立于依赖项的情况下对代码进行单元测试,这样您就可以在“单元”级别真正测试一段代码。被测试的代码是真实的,它所依赖的每一段代码(通过参数或依赖项注入等)都是一个“Mock”(一个空的实现,在调用它的一个方法时总是返回期望值)

mock一开始可能看起来很乏味,但是一旦你掌握了使用它们的窍门,它们会使单元测试变得更加容易和健壮。大多数语言都有模拟库,这使得模拟变得相对简单。如果您正在使用Java,我将推荐我个人最喜欢的:


让我用这个想法来结束:您也需要集成测试,但是有大量的单元测试可以帮助您找出哪个组件包含bug(当bug存在时)。

是的,这是使用mock进行测试的缺点。你需要投入大量的工作,这让你觉得很残酷。但这就是单元测试的本质。如果你不模仿外部资源,你怎么能孤立地测试一些东西呢

另一方面,你在嘲弄缓慢的乐趣