我应该练习“模拟”还是“经典”TDD?

我读过(并重读)Martin Fowler的Mocks不是存根(stub) 。 其中,他定义了两种不同的TDD方法:“古典”和“Mockist” 。 他试图回答这个问题:“ 我应该成为一个古典主义者还是嘲笑者? ”,但是他承认,他从来没有尝试过“嘲笑TDD”的玩具。 所以我想我会在这里问这个问题。 自Fowler上次在2007年1月更新文章以来,好的答案可能会重复Fowler的论点(但希望更清楚)或者添加他没有想到的或其他人提出的论点。

我不认为你需要select一个。 两者都有其优点和缺点,都是你的工具箱的工具。 “Mockist”TDD让你在testing中可以更加灵活一些,而经典的TDD让你的testing不那么脆弱,因为他们往往更注重input/输出,而不是看实际的实现。 在进行模拟unit testing时,在更改实现时似乎有更多的testing中断。

尽可能使用经典的TDD(尽pipe我经常使用一个模拟框架来快速设置存根)。 有时我注意到我一次开始testing的太多,或者我需要太多的对象来设置testing。 那时候,模拟testing通常可以帮助你设置更小的testing。

这一切都很抽象,所以我希望我有道理

关于mockist或经典tdd的问题非常关于您正在testing的应用程序的哪一部分。 如果你有一个“标准的”分层体系结构(比如DDD ),那么域层通常适用于通过设置被测对象进行unit testing的传统tdd,调用一些方法并检查结果和/或状态。

另一方面,当你testing应用程序服务,控制器或performance逻辑时,所有这些工作都会协调工作,通常需要嘲笑或剔除以获得良好的testing。 我的经验也是这些类倾向于调用你真正想要模拟或存根的其他层(webservice,datalayer,…)。 这些unit testing也需要更多的设置代码,所以你只能在必要的时候模拟。

我的build议是,只要有可能,就去经典,当你一定要嘲笑。

你可以考虑看看我们的书,在http://www.growing-object-oriented-software.com/ 。 它包括一个扩展的工作示例。 正如我们写的那样,我们发现状态与交互的区别在很大程度上是误导性的,更多的是关于面向对象devise的方法。

Sandi Metz揭露了一个非常实用的方法:

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

有四种组合。 传出的查询消息不应该被testing(已经作为外部类的传入查询来testing)你可以对传出的查询消息使用mockisttesting方法,其余的可以使用经典testing。 检查链接

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

我在TDD方面还是比较新的 – 但是我被教导/介绍到差异的方式是从testing类之间的整合的angular度来考虑,以便不依赖实时数据。 例如,如果我有一个非常独立的类 – 不依赖于我为某个项目构build的其他类,并且不会输出到实时数据/开发环境以进行input(如数据库或API)一个系统),那么我只会使用像NUnit或JUnit这样的经典unit testing – 但是当我开始testing构build类之间的交互时 – 这是什么时候可以真正方便地模拟其他自定义类和/或外部交互 – 让你可以挑出并testing你当前的类的代码,而不用追查你正在调用的其他类中的潜在错误。