我读过(并重新阅读)Martin Fowler的Mocks Are not Stubs.在其中,他定义了两种不同的TDD方法:"古典"和"模仿者".他试图回答" 我应该成为一个古典主义者还是一个嘲笑者? "这个问题,但他承认他从来没有尝试过模仿者TDD,而不仅仅是"玩具".所以我想我会问这个问题.好的答案可能会重复福勒的论点(但希望更清楚)或添加他没有想到的论点,或者其他人提出的论点,因为福勒上次在2007年1月更新了这篇论文.
我不认为你需要选择一个而不是另一个.两者都有它们的优点和缺点,它们都是工具箱的工具."Mockist"tdd让你在测试的内容上更加灵活,而经典的TDD使你的测试变得不那么脆弱,因为他们倾向于更多地关注输入/输出,而不是看实际的实现.在进行mockist单元测试时,我似乎在更改实现时会有更多测试中断.
我尝试尽可能使用经典的tdd(尽管我经常使用模拟框架来快速设置存根).有时我注意到我一次开始测试太多,或者我需要太多的对象来设置测试.那时,模拟测试通常可以帮助您设置较小的测试.
这一切都很抽象,所以我希望我有意义
关于mockist或classic tdd的问题非常关乎你正在测试的应用程序的哪个部分.如果您有一个"标准"分层体系结构(例如DDD),域层通常适用于经典tdd,您可以通过设置测试对象进行单元测试,调用几个方法并检查结果和/或状态.
另一方面,当您测试所有执行更多协调工作的应用程序服务,控制器或表示逻辑时,通常需要进行模拟或存根以获得良好的测试.我的经验也是这些类倾向于调用你真正想要模拟或存根的其他层(webservice,datalayer,...).这些单元测试还需要更多的设置代码,因此您只能在必要时进行模拟.
我的建议是尽可能去经典,并在必要时嘲笑.
您可以考虑查看我们的书,网址为http://www.growing-object-oriented-software.com/.它包括一个扩展的工作示例.正如我们所写的那样,我们发现状态与交互的区别在很大程度上是误导性的,它更多地是关于一个人对OO设计的方法.
Sandi Metz揭示了一种非常实用的方法:
一个对象可以通过传出消息或传入消息与其他对象进行通信。消息可以是查询(返回内容)或命令(执行内容)。
有四种组合。不应测试传出查询消息(已经作为外部类的传入查询进行了测试)您可以对传出的命令消息使用模拟测试方法,对其余命令使用经典测试。
检查链接
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
优酷