【问题标题】:Is it in considered a good practice to mock in integration test? [closed]在集成测试中进行模拟是否被认为是一种好习惯? [关闭]
【发布时间】:2018-08-31 02:02:53
【问题描述】:

有人告诉我@Mock 通常只用于单元测试,但我认为它对于替换测试类之外的外部部分很有用。在集成测试中模拟是否正确?

【问题讨论】:

  • 我已将 VTC 视为基于意见,但简短的回答是肯定的。
  • 如果被测单元的每个依赖项都被模拟,则没有与任何外部单元集成,因此测试不是集成测试。另一方面,如果一次测试一个依赖项的集成,模拟其他依赖项,它仍然可以。
  • 我不认为这个问题是基于意见的。这是一个非常相关且重要的问题,可以回答是或否。

标签: java spring mocking mockito


【解决方案1】:

最后,这都是关于措辞的。

当您从最基本的意义上考虑“正确”时,例如correctness,那么答案很简单:不。

您知道,集成测试的目标是确保您的集成系统(由多个不同的组件组成)按预期运行。集成测试的目的是验证您的组件“管道”是否按预期工作。因此:当系统的部分被模拟出来时,您无法验证您的系统是否正常工作。

但是,您可以不那么严格地考虑“正确性”。

示例:销售汽车的公司必须测试ECUs。基本上是一个硬件,运行一个潜在的巨大软件堆栈。这些 ECU 通常在 汽车 内运行。所以当你想对一个ECU进行集成测试时,你必须把ECU放到汽车中进行测试,对吧?一辆可能还不存在的汽车。这里的解决方案:有硬件模拟器。您将 ECU 插入该仿真器,然后 ECU 会“思考”位于真车内的内容。

所以:有很好的论据声称“真正的集成测试不能使用模拟”,但与此同时,在现实世界中,这种“模拟”一直在发生。

因此,真正的答案是:这取决于上下文。因此,没有一个普遍的答案。相反,这是关于沟通。您“只需”确保您的组/组织中的所有人都对这些术语有相同的理解。

这个词本身可以用不同的方式来解释。您(共同!)选择最适合您需求的定义,然后确保所有为您的项目做出贡献的人都共享该观点(或至少了解它)。

【讨论】:

    【解决方案2】:

    是的,在某些情况下您可以在集成测试中使用@Mock(主要用于存根)。特别是如果您想集成测试类的一部分。

    例如,如果您想测试与外部服务 A 的通信,那么模拟与服务 B 通信有关的其余部分没有任何问题。

    另一个例子,如果您测试一个工作流,那么通过模拟单个步骤/活动来测试路径的集成测试是有意义的。

    个人意见(有争议并且有许多不同的术语):单元测试和集成测试有很多种。据我了解,单元测试只是单独测试一个类。但我经常编写测试多个类的组合,在我看来这已经是一种集成测试。还有一些测试可以通过模拟外部服务来测试单个组件,我称之为系统测试。然后可能会有针对未模拟的外部服务测试单个组件的测试,我将这些测试称为系统集成测试。在所有这些场景中,模拟/存根某些部分并专注于单个测试类中的一个方面可能是可行的。

    【讨论】:

    • 很好的答案,实际上这些东西不是白色或黑色的。不是直接的问题,但正如你所说,我想发表我的意见。关于编写集成测试,我认为重要的是选择那些有价值的。集成测试可以在多个级别进行。我们必须做出正确的选择,以免增加测试数量并在测试代码中引入一些重复。
    【解决方案3】:

    在集成测试中模拟是否正确?

    一般情况:您不在集成测试中模拟

    一般来说,模拟和集成测试并不适合。
    大多数时候,你想使用一个或者你想使用第二个,而不是两者。

    但有时您想在集成测试中进行模拟,因为您要断言的逻辑只能在此框架中正确测试

    如果您依赖一个框架或库来为您执行很多事情,并且您需要测试您在此框架中指定的逻辑,那么您将通过编写比单元测试更多的集成测试来完成,因为单元测试通常是不够的完全覆盖应用程序代码。
    但是完全集成测试与其他组件完全没有隔离(因此可能会产生副作用:由于不好的原因,测试可能会成功),这些通常很慢,因此通常不会在本地机器上执行,这会为开发人员提供后期反馈.
    所以只写完整的集成测试通常是不可接受的。 对于这种上下文,在集成测试期间模拟的想法非常有意义。

    Spring Boot 和测试切片:一个很好的例子

    由 Spring Boot 启动的应用程序属于此类。
    事实上,我们希望运行容器以测试某些特定部分(持久性、控制器等),但我们不想加载整个容器和相关组件。
    因此,模拟某些特定部分非常有意义。
    Spring Boot 中的Test slices 允许在被测组件在某种集成级别上进行测试时进行模拟:

    Spring Boot 的自动配置系统适用于应用程序 但有时对于测试来说可能有点太多了。它通常有助于 仅加载测试所需的配置部分 应用程序的“切片”。例如,您可能想要测试 Spring MVC 控制器正确映射 URL,而您不希望 在这些测试中涉及数据库调用,或者您可能想要测试 JPA 实体,而您对 Web 层不感兴趣时 测试运行

    【讨论】:

    • 是的,我同意。如果不关注应用程序的某些方面,这些测试会因与他们正在测试的部分无关的问题而失败,并且由于它们的复杂性,它们将很难维护。在我看来,这个例子很好地说明了为什么在集成测试中模拟/存根部分系统是有用的并且完全可以接受的。
    • @mio 你引用的观点鼓励我重新表述。谢谢
    • @GhostCat 那是可能发生的事情:)
    【解决方案4】:

    有两种类型的测试。单元测试和集成测试。 您可以使用 Mocks 来执行单元测试。在单元测试中,您测试单个方法,重点是测试单个方法的行为。因此,在单元测试的情况下,使用模拟是有意义的。

    您不能使用模拟来执行集成测试。集成测试通常涉及集成的所有依赖系统,我们在任何服务器/云上执行它。

    【讨论】:

    • 还有功能测试。和系统测试。还有功能测试等等……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 2014-03-18
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多