Unit testing 如何使用模拟?
当我最初被介绍到模拟时,我觉得主要目的是模拟来自外部数据源的对象。这样,我就不必维护一个自动化的单元测试数据库,我可以伪造它 但现在我开始有了不同的想法。我想知道mock是否能更有效地将测试方法与自身之外的任何东西完全隔离开来。不断浮现在脑海中的图像是你在绘画时使用的背景。你不想让油漆到处都是。我只是在测试那个方法,我只想知道它对这些伪造的外部因素有什么反应 这样做似乎令人难以置信地乏味,但我看到的好处是,当测试失败时,这是因为它是错误的,而不是16层。但现在我必须进行16次测试才能获得相同的测试覆盖率,因为每一件产品都要单独测试。此外,每项测试都变得更加复杂,与测试方法的联系也更加紧密Unit testing 如何使用模拟?,unit-testing,mocking,Unit Testing,Mocking,当我最初被介绍到模拟时,我觉得主要目的是模拟来自外部数据源的对象。这样,我就不必维护一个自动化的单元测试数据库,我可以伪造它 但现在我开始有了不同的想法。我想知道mock是否能更有效地将测试方法与自身之外的任何东西完全隔离开来。不断浮现在脑海中的图像是你在绘画时使用的背景。你不想让油漆到处都是。我只是在测试那个方法,我只想知道它对这些伪造的外部因素有什么反应 这样做似乎令人难以置信地乏味,但我看到的好处是,当测试失败时,这是因为它是错误的,而不是16层。但现在我必须进行16次测试才能获得相同的测
我觉得这是对的,但也很残酷,所以我想知道别人怎么想。是的,我同意。我认为嘲弄有时是痛苦的,但通常是必要的,这样你的测试才能真正成为单元测试,也就是说,只有你能让你的测试关注的最小单元在测试中。这允许您消除可能影响测试结果的任何其他因素。您最终会得到更多的小测试,但要找出代码的问题所在就变得容易多了。不要走黑暗的道路(大师卢克):)不要嘲笑一切。你可以,但你不应该。。。原因如下
- 如果你继续孤立地测试每一种方法,当你把它们结合在一起时,你会有惊喜,也会有特别的工作。我们构建对象,以便它们能够共同解决更大的问题。。它们本身是微不足道的。您需要知道所有合作者是否都按预期工作
- mock通过引入复制使测试变得脆弱-是的,我知道这听起来令人担忧。对于您设置的每个mock expect,有n个地方存在您的方法签名。实际代码和模拟预期(在多个测试中)。更改实际代码更容易。。。更新所有的模拟期望是乏味的李>
- 您的测试现在可以了解内部实施信息。因此,您的测试取决于您选择如何实现解决方案。。。糟糕。测试应该是一个可以由多个解决方案满足的独立规范。我应该可以自由地在代码块上按delete键并重新实现,而不必重写测试套件。。因为需求仍然保持不变
这是基于国家的测试与基于实践的测试之间的圣战。。谷歌搜索会给你更深的洞察力 澄清:我在这里进行了一些阻力w.r.t.集成测试:)为了澄清我的立场
- 模拟不在“验收测试”或集成领域中。您只能在单元测试世界中找到它们。。这就是我的重点
- 验收测试是不同的,非常需要,而不是贬低它们。但是单元测试和验收测试是不同的,应该保持不同
- 组件或包中的所有协作者不需要彼此隔离。。就像是过度的微观优化。它们的存在是为了一起解决问题。。凝聚力李>
不编写适合代码的测试 至于复杂性,我的观点是,测试应该简单易写,因为如果需要,您可以编写更多的测试 我可能同意,如果您正在模拟的类没有测试套件,那么这可能是一个好主意,因为如果它们确实有一个适当的测试套件,您将知道在没有隔离的情况下问题在哪里
我使用模拟对象的大部分时间是在我编写测试的代码紧密耦合(读:糟糕的设计)的情况下,当它们所依赖的类不可用时,我不得不编写模拟对象。当然,mock对象有一些有效的用法,但是如果您的代码需要它们的用法,我会再看一看设计。我建议您看看Martin Fowler的文章,以获得比我能给您的更权威的mock处理方法 mock的目的是在独立于依赖项的情况下对代码进行单元测试,这样您就可以在“单元”级别真正测试一段代码。被测试的代码是真实的,它所依赖的每一段代码(通过参数或依赖项注入等)都是一个“Mock”(一个空的实现,在调用它的一个方法时总是返回期望值) mock一开始可能看起来很乏味,但是一旦你掌握了使用它们的窍门,它们会使单元测试变得更加容易和健壮。大多数语言都有模拟库,这使得模拟变得相对简单。如果您正在使用Java,我将推荐我个人最喜欢的:
让我用这个想法来结束:您也需要集成测试,但是有大量的单元测试可以帮助您找出哪个组件包含bug(当bug存在时)。是的,这是使用mock进行测试的缺点。你需要投入大量的工作,这让你觉得很残酷。但这就是单元测试的本质。如果你不模仿外部资源,你怎么能孤立地测试一些东西呢 另一方面,你在嘲弄缓慢的乐趣