【问题标题】:Should I practice "mockist" or "classical" TDD?我应该练习“mockist”还是“经典”TDD?
【发布时间】:2008-10-08 20:16:03
【问题描述】:

我已阅读(并重新阅读)Martin Fowler 的 Mocks Aren't Stubs。在其中,他定义了two different approaches to TDD: "Classical" and "Mockist"。他试图回答“So should I be a classicist or a mockist?”这个问题,但他承认他从未在“除了玩具”上尝试过 mockist TDD。所以我想我会在这里问这个问题。好的答案可能会重复 Fowler 的论点(但希望更清楚)或添加自 Fowler 上次于 2007 年 1 月更新文章以来他没有想到或其他人提出的论点。

【问题讨论】:

    标签: tdd mocking


    【解决方案1】:

    我认为您不需要选择其中之一。两者都有其优点和缺点,两者都是您工具箱的工具。 “Mockist” tdd 使您在可以测试的内容上更加灵活,而经典 TDD 使您的测试不那么脆弱,因为它们倾向于更多地查看输入/输出而不是查看实际的实现。在进行模拟单元测试时,我似乎在更改实现时有更多测试中断。

    我尽可能使用经典的 tdd(尽管我经常使用模拟框架来快速设置存根)。有时我注意到我一次开始测试太多,或者我需要太多对象来设置测试。那时,mockist 测试通常可以帮助您设置较小的测试。

    这一切都很抽象,所以我希望我有意义

    【讨论】:

    • 你好。自从您回答以来已经有一段时间了,但是我正在努力了解您实际上是如何进行经典 TDD 的。如果我有一个带有signUpUser 方法的UserService,则依赖于密码哈希、数据验证、电子邮件发送、存储库等。Classical TDD 是否说要为所有这些部门创建“假货”(而不是模拟)或尽可能使用真实的?当然,您必须伪造电子邮件服务和存储库。如果是这样,它仍然是“单元”测试吗?谢谢。
    • 嗨 Jamie,根据您的描述,我认为“传统”tdd 不适合您在这种情况下使用。当您测试独立的函数时,传统的 tdd 效果很好。但是您描述的代码听起来像是在编排多个依赖项的操作。 mockist tdd 听起来是适合这项工作的工具。
    【解决方案2】:

    关于 mockist 或经典 tdd 的问题很大程度上是关于您正在测试应用程序的哪一部分。如果您有一个“标准”分层架构(例如 DDD),那么域层通常适合经典 tdd,您可以在其中通过设置被测对象进行单元测试,调用一些方法并检查结果和/或状态。

    另一方面,当您测试应用程序服务、控制器或表示逻辑时 它们都做了更多的协调工作,通常需要模拟或存根才能获得良好的测试。我的经验也是,这些类往往会调用您真正想要模拟或存根的其他层(webservice、datalayer...)。这些单元测试还需要更多设置代码,因此您应该只在必要时进行模拟。

    我的建议是尽可能经典,必要时模仿。

    【讨论】:

    • 你的答案在今天仍然适用吗 - 将近十年了? +1。
    • 我会这么说。框架已经改变,但我仍然以几乎相同的方式进行单元测试。
    【解决方案3】:

    您可以考虑查看我们的书,地址为http://www.growing-object-oriented-software.com/。它包括一个扩展的工作示例。在我们撰写本文时,我们发现状态与交互的区别在很大程度上具有误导性,而且更多的是关于一个人的 OO 设计方法。

    【讨论】:

    • 史蒂夫,我读过这本书,但我错过或忘记了关于状态与交互的误导部分。这个主题是直接在书中提到的,还是贯穿整个内容的环境主题?你能指出我可以在书中找到它的章节或章节吗?
    【解决方案4】:

    Sandi Metz 揭露了一种非常务实的做法:

    一个对象可以通过传出或传入消息与其他对象通信。消息可以是查询(返回某些内容)或命令(执行某些内容)。

    有四种组合。不应测试传出查询消息(已作为外部类的传入查询进行测试)您可以对传出命令消息使用 mockist 测试方法,并对其余消息使用经典测试。

    检查链接

    http://jnoconor.github.io/blog/2013/10/07/the-magic-tricks-of-testing-by-sandi-metz/

    https://speakerdeck.com/skmetz/magic-tricks-of-testing-ancientcityruby

    Youtube

    【讨论】:

      【解决方案5】:

      我在 TDD 方面仍然相对较新 - 但我被教导/介绍差异的方式是从测试类之间的集成的角度来考虑它,这样您就不会依赖实时数据。例如,如果我有一个非常独立的类 - 不依赖于我为项目构建的其他类,并且它不会进入实时数据/开发环境进行输入(如 DB 或 API一个系统)然后我只会在 NUnit 或 JUnit 之类的东西中使用经典单元测试 - 但是当我开始测试构建类之间的交互时 - 那时它可以真正方便地模拟其他自定义类和/或外部交互 - 这样你可以挑出并测试您当前类的代码,而无需试图追查您正在调用的其他类中的潜在错误。

      【讨论】:

      • 这与功能测试与单元测试有关吗?
      猜你喜欢
      • 2018-09-02
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-05
      • 2010-10-16
      • 1970-01-01
      相关资源
      最近更新 更多