【问题标题】:How is unit testing testing anything?单元测试如何测试任何东西?
【发布时间】:2018-12-20 20:26:30
【问题描述】:

我不明白我是如何使用单元测试来测试任何东西的。

假设我正在测试我的存储库类是否可以正确地从数据库中检索值。执行此操作的正确方法是实际调用真实数据库并检索和检查这些值。

但是单元测试背后的想法是它应该独立完成,连接到正在运行的数据库并不是孤立的。所以通常做的是mockstub 数据库。

但是,为什么要在带有硬编码数据和硬编码返回值的假数据库上进行测试,甚至会测试任何东西呢?这似乎是同义反复并且浪费时间。

还是我不明白如何正确进行单元测试?

甚至对数据库调用进行单元测试吗?

【问题讨论】:

    标签: unit-testing testing tdd


    【解决方案1】:

    我不明白我是如何使用单元测试来测试任何东西的。

    简短回答:您正在测试逻辑,并忽略了副作用

    你没有测试一切;但你正在测试一些东西。

    此外,如果您牢记您并没有真正测试带有副作用的代码,那么您就有动力来安排您的代码,以便真正依赖于副作用的部分是小的。大块实际上并不关心数据来自哪里,因为它们很容易测试。

    所以“某事”可以是“大多数事情”。

    存在阻抗问题 - 如果您的测试替身未能充分模拟生产原件,那么您的某些测试结果将不准确。

    我的理念是尽可能少地测试以达到给定的信心水平

    Kent Beck, 2008

    想象“尽可能少”的一种方法是从成本的角度来考虑——我们的目标是给定的置信水平,因此我们希望使用廉价的单元测试尽可能多地实现这种置信度,然后用更昂贵的技术弥补差额。

    Cory Benfield 的演讲 Building Protocol Libraries the Right Way 描述了我们在这里讨论的那种分离的例子。如何解析 HTTP 消息的逻辑与读取字节的问题是分开的。如果你让复杂的部分容易测试,而难以测试的部分简单到不能失败,你成功的机会就很大。

    【讨论】:

      【解决方案2】:

      我认为您的担忧是有道理的。对我来说,与单元测试实践相比,TDD 更像是一种进化设计实践,但我将把它留到另一个讨论中。

      在您的示例中,我们真正测试的是您的各个类中包含的逻辑是否合理。通过对来自数据库的数据进行存根处理,您可以获得一个受控场景,您可以确保您的代码适用于该特定场景。这使得确保所有数据场景的完整测试覆盖率变得更加容易。您说得对,这实际上并没有测试整个系统端到端,但关键是降低整体测试维护成本并实现更快的反馈。

      我的方法是在单元测试级别模拟大多数协作者,然后在集成测试级别编写验收测试,这会使用真实数据验证您的系统。由于使用模拟数据的单元测试允许您测试各种数据场景,因此您只需使用集成测试测试其中一些场景,即可确信您的代码将按预期执行。

      【讨论】:

        【解决方案3】:

        您可以针对实际数据库单独测试您的代码。只需为每个测试创建新的数据库实例,或者一个接一个地同步执行测试并在下一次测试之前清理数据库。

        但是使用实际的数据库会使您的测试变慢,这会减慢您的工作,因为您需要快速反馈您所做的事情。

        不要测试每个类 - 测试主要功能逻辑,它可以使用许多不同的类和仅模拟/存根依赖项,这会使测试变慢。

        无需模拟即可找到您的应用程序边界并测试它们之间的逻辑。
        例如在琐碎的 web api 应用程序边界可以是:
        - 控制器动作 -> 请求(输入)
        - 控制器动作 -> 响应(输出)
        - 数据库 -> 收到请求的副作用。

        假设我们生活在一个完美的世界中,新的数据库和网络服务器的设置需要几毫秒。然后您将测试应用程序的整个管道:
        1. 配置数据库进行测试
        2. 向web api服务器发送请求
        3. 断言响应包含预期数据
        4. 断言数据库状态按预期改变了

        但在当今世界,您的边界将是控制器操作和抽象的数据库访问点。这使您的测试如下所示:
        1.配置mocked数据库访问点(repository)
        2. 使用给定参数调用控制器动作
        3. 断言操作返回预期结果
        4. 可能断言模拟存储库收到了预期的更新参数。

        如果您的应用程序没有逻辑,只需从数据库中读取/更新数据 - 使用实际数据库进行测试,或者,如果您的数据库框架允许,则使用内存中的数据库。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-15
          • 2012-02-20
          • 2017-07-10
          • 1970-01-01
          • 1970-01-01
          • 2021-02-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多