【问题标题】:Why do we need mocking frameworks like Easymock , JMock or Mockito?为什么我们需要像 Easymock、JMock 或 Mockito 这样的模拟框架?
【发布时间】:2010-05-04 12:09:30
【问题描述】:

我们在单元测试中使用手写存根,我正在探索在我们的项目中是否需要像 EasyMock 或 Mockito 这样的 Mock 框架。

我没有找到从手写存根切换到 Mocking 框架的令人信服的理由。

任何人都可以回答为什么当他们已经使用手写的模拟/存根进行单元测试时会选择模拟框架。

谢谢

【问题讨论】:

标签: unit-testing tdd mocking easymock stubs


【解决方案1】:

简单的答案是我们不需要需要它们。

我们也不需要其他现有的框架,但使用 Mocking 框架让我们的生活更轻松。作为开发人员,我们可以将更多时间花在手头的问题上,而不是创建或执行模拟框架可以做的事情。

"我找不到令人信服的理由 从切换到 Mocking 框架 手写存根。”

我完全一样。我为什么要费心学习一个模拟框架?手写存根就可以了。

我想到了几点,主要是一段时间后,您的测试会因测试存根而变得晦涩难懂。您在使用手写存根时所指的内容称为测试扩展。您扩展代码以启用模拟框架的功能。换句话说,您将代码写入存根,或根据发生的情况返回值。这需要时间和精力。更不用说空间了。一个模拟框架可以在几行代码中完成所有这些工作。

模拟框架的好处是:

  • 更容易(主观,但过一段时间你就不会手写实现了
  • 更少的代码(框架允许您在几行中创建一个模拟,而不是完整的类声明
  • 遵循 DRY(您最终不会重复模拟实现

当您需要模拟对象时,最大的好处就出现了。必须手写代码来检查一个方法是否被调用、调用了多少次等等,这本身就是一个小任务。如果其他人已经这样做了,并创建了一个经过全面测试、有据可查的框架,那么不使用它是没有意义的。就像任何框架一样,没有它你也可以正常工作,但有时使用正确的工具会使工作变得容易得多。

【讨论】:

  • 如前所述,值得查看“Mocks 不是存根” 文章。模拟框架允许模拟、存根和伪造。换句话说,它们用途广泛。
【解决方案2】:

您可能想阅读 Martin Fowler 的 Mocks Aren't Stubs 文章。基本区别是这样的:

  • 存根的工作是将已知结果返回给所有调用
  • mock 还期望调用以特定顺序和特定参数进行,并且在不满足这些期望时会抛出异常。

有些错误情况无法使用存根进行测试。另一方面,使用模拟的测试通常不太稳定。

虽然可以通过合理的努力手动编写存根,但 Mocks 需要更多的工作。一个好的模拟框架也可以让编写存根更快、更容易。

【讨论】:

  • 小点,马丁的文章现在有点老了,漏掉了一些关键点。首先,除非您要求,否则我认为当前的任何框架都不会强制执行调用顺序。其次,如果您的测试不稳定,这是有用的反馈,应该会让您重新审视您的设计。
【解决方案3】:

就像所有其他开发人员一样,我发现自己在编写代码而不是使用现有的解决方案——“不是这里发明的”综合症。

您的问题表明您更愿意编写需要伪造/模拟两次的类,而不是使用可以为您完成此操作的框架。使用模拟框架使您无需在更改伪造对象时编写、重构和更新您的手动模拟。

换句话说,使用模拟框架就像任何其他 3rd 方库一样,例如ORM - 其他人编写了代码,因此您不必这样做。

【讨论】:

    【解决方案4】:

    我以同样的方式开始(手动编写模拟),现在我几乎完全切换到 EasyMock。

    我发现使用 EasyMock 通常更快、更灵活。

    通常,当我第一次需要模拟时,我可以使用 EasyMock 在几行代码中获得它,而我需要手动实现所需的接口(公平地说,这可以由 IntelliJ 之类的 IDE 生成) 然后添加必要的代码以产生所需的响应和/或允许感知对其调用的影响。

    好吧,有人可能会说,这只是一次性费用。下次我可以愉快地重复使用手写模拟......我发现通常情况并非如此。在另一个测试中,我可能需要一个具有不同行为的同一类的模拟。例如。调用不同的方法,和/或预期不同的结果。一个特定的情况是当 mock 预计会在一个测试用例中抛出异常,但不会在另一个测试用例中抛出异常。好吧,我可以添加一些参数来动态控制行为。然后对于下一个测试,更多的参数来控制更多的行为......所以我最终得到了一个更复杂的模拟实现,这是对更多单元测试的依赖——也带来了无意中破坏旧测试的风险。

    与此相反,使用 EasyMock,我可以为每个测试独立配置我的模拟。因此,该行为在单元测试代码本身中是明确控制和可见的,并且没有副作用的风险。

    更不用说,使用 EasyMock,您可以验证是否按要求的顺序调用了所需的方法,如果您需要(我不时这样做)。手动实现这一点(特别是以通用方式)将非常痛苦,没有额外的好处。

    【讨论】:

      【解决方案5】:

      有时以声明方式创建模拟可能更容易,它可以帮助您使用框架比手动更轻松地编写某些行为。另一个小优势可能是,通过使用模拟框架,您可以明确地进行模拟。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-11
        • 2018-01-30
        • 1970-01-01
        • 2011-03-04
        • 2012-11-30
        • 1970-01-01
        • 2021-04-28
        相关资源
        最近更新 更多