【问题标题】:How to avoid duplicate code when using mocks in unittests在单元测试中使用模拟时如何避免重复代码
【发布时间】:2010-09-29 20:25:54
【问题描述】:

我正在使用依赖注入来为我的测试类之外的代码提供模拟。我发现自己一遍又一遍地编写了很多相同的代码,因为我需要模拟在我想要测试的方法中使用的 AuthProvider、ConfigurationManager 等。该方法包含分支(if-then-else),因此我有多个测试来测试该方法的所有执行路径。我多次实例化每个模拟(在每种测试方法中一次),但我想知道这是否是错误的方法? 此外,我对模拟和预设响应提出了期望,这些响应显然主要是复制粘贴,因为在每个方法中都会调用诸如 AuthProvider.Authenticate() 之类的调用

在每个方法中,我都设置了一个模拟存储库,并在每个方法结束时验证了模拟存储库。我是否应该有某种工厂来创建这些模拟以及设置它们的期望和返回值,如果是的话,如何?

为了实现模拟,我使用的是 RhinoMocks。

【问题讨论】:

    标签: unit-testing dependency-injection mocking rhino-mocks


    【解决方案1】:

    “多次实例化每个模拟”不是问题。对象是免费的。

    请确保您没有多次定义模拟类。上课很贵。

    此外,您在 TestCase 中有一个“setUp”方法,它允许您创建一个可供所有测试使用的夹具。是的,它为每个测试重建。不,这不是问题,除非它非常缓慢。

    【讨论】:

      【解决方案2】:

      假设您使用的是 NUnit,您可以为您的 Mocks 使用实例变量并在 Setup/Teardown 中重置它们。如果您看到重复的模式,那么就按照您对生产代码所做的事情:重构并提取帮助方法来表达您想要实现的目标(如果根本没有共性,那么生产代码的设计就有问题)。

      如果设置中存在重大差异,请考虑为您的生产类编写多个测试类。

      最后,想想你的生产类是否太忙了,一些行为应该被提取到一个辅助对象中。

      聆听测试!

      【讨论】:

      • 非常感谢有见地的回答。我想知道如何为生产类编写多个测试类..我将如何命名多个测试类?
      • 用它们的重要意义命名测试类——就像你所有的其他类一样:)
      【解决方案3】:

      这是我的看法..

      在这种情况下我不会使用模拟...我会使用工厂方法来返回类的假实现并使用依赖注入来代替使用此实现..这样您可以避免重复并可以重用此实现再次n再次......再次需要正确重构这个工厂实现,即没有重复......

      Mocks,我想应该在您测试一些动态行为时使用.. 类似.. 当我对 SUT 执行某些操作时调用了子系统中的方法.. 稍后调用 verify() 进行验证这种行为... Martin Folwer bliki Mock Aren't Stubs也有一篇好文章

      【讨论】:

        【解决方案4】:

        您可能希望考虑使用 AAA 样式的测试,以便使用通用设置进行多个测试。 Here's a decent example.

        【讨论】:

          【解决方案5】:

          如果您不对模拟调用设置期望值,EasyMock 等记录和回放框架就会失败。但是像 Mockito 这样的框架只是简单地记录所有调用并让您只验证重要的调用。所以你不必对所有测试中的所有方法都设定期望。

          回到您在每个测试方法中实例化 Mocks 的问题上,有比使用 setUp() 方法更好的方法。 Mockito 提供了一个 @Mock 注释。所以你声明你的变量(作为字段),如: @Mock Repository repositoryMock

          只需在 setUp() 中调用 initMocks()。声明的所有模拟对象在您的测试中自动可用,无需显式创建模拟。

          【讨论】:

          • “如果你不对模拟调用设置期望,像 EasyMock 这样的记录和回放框架会失败。” => 这是不正确的。所有的模拟工具,包括 EasyMock,都允许开发者有“非严格”的期望。在 EasyMock 中,您可以通过使用“createNiceMock()”方法创建一个“不错的”模拟来做到这一点。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-26
          相关资源
          最近更新 更多