我已成功使用单元测试一段时间,但我开始认为它们只适用于实际执行大量逻辑的类/方法 - 解析器,数学运算,复杂的业务逻辑 - 一切都很好候选人进行测试,毫无疑问。我真的很难弄清楚如何使用另一类对象的测试:主要通过委托操作的那些。
例证:我当前的项目协调了很多数据库和服务。大多数类只是服务方法的集合,大多数方法执行一些基本的条件逻辑,可能是for-each循环,然后调用其他服务。
对于这样的对象,模拟实际上是唯一可行的测试策略,所以我尽职尽责地为其中几个设计了模拟。我真的,真的不喜欢它,原因如下:
我的应用程序的核心是所有部分如何协同工作,所以我正在考虑 开沟单元完全测试(除了他们显然是合适的地方)并转而进行外部集成测试 - 更难设置,覆盖更少的可能情况,但实际上是运行系统,因为它意味着运行。
我没有看到任何使用模拟实际上有用的情况。
思想?
答案 0 :(得分:3)
如果你可以编写快速可靠的集成测试,那么我会说它去吧。 仅在必要时使用模拟和/或存根来保持测试。
请注意,使用模拟并不一定像您所描述的那样痛苦:
答案 1 :(得分:2)
在我看来,单元测试应该进行测试 功能,而不是指定“ 方法需要做A,然后B,然后C, 没有别的,按顺序。“
我同意。正如您所发现的,使用模拟进行行为测试可能会导致脆弱的测试。使用存根进行基于状态的测试可以减少该问题。福勒在Mocks Aren't Stubs中权衡了这一点。
编写模拟通常更有效 而不是自己写课程
对于模拟或存根,请考虑使用隔离(模拟)框架。
最后,我的所有测试都真的验证了 是最基本的骨架 行为:“如果”和“为” 陈述仍然有效
分支和循环是逻辑;我建议测试它们。在我看来,没有必要测试getter和setter,单行纯委托方法等等。
集成测试对于像您这样的复合系统非常有价值。除了单元测试之外,我会推荐它们,而不是代替它们。
您肯定希望测试低级或组合服务的基础类;那就是你会看到最大的收获。
编辑:福勒不会像我想象的那样使用“经典”术语(这可能意味着我错了)。当我谈到基于状态的测试时,我的意思是将存根注入到被测试的类中,用于任何依赖项,作用于被测试的类,然后针对被测试的类进行断言。在纯粹的情况下,我不会验证存根上的任何内容。
答案 2 :(得分:0)
写Integration Tests是一个可行的选择,但不应取代单元测试。但是既然你自己说过你的写作模拟,我建议使用一个隔离框架(又称模拟框架),我相信它也可以用于你的环境。
答案 3 :(得分:0)
因为你已经在一个问题上发了几个问题,我将逐一回答。
如何为主要面向服务的应用程序编写有用的单元测试?
不要依赖于“主要面向服务的应用程序”的单元测试!是的我在一句话中说过。这些类型的应用程序旨在做一件事:集成服务。因此,编写集成测试而不是单元测试非常紧迫,因为集成工作正常。
我没有看到任何使用模拟实际上有用的情况。
模拟可能非常有用,但我不会在控制器上使用它们。控制器应该由集成测试覆盖。服务可以由单元测试覆盖,但如果测试量减慢了您的项目,将它们作为单独的模块可能是明智的。
思想?
对我来说,我倾向于考虑一些事情:
在您提供的方案中,我会说您的应用程序 是许多服务的集成。因此,我非常依赖单元测试的集成测试。我敢打赌你写的大部分模拟都是用于http相关课程等。
由于以下原因,我在可能的情况下更喜欢集成/系统级测试: