Repo 中,每个测试替身的例子都自成一个包。每个测试替身的例子都不相关, 因此大家可以按需看代码。
-
最简单、最原始的测试替身型别。
-
Dummy 没有实现,最常用于需要参数值但不使用它的情况。
-
Null 可以看作是 Dummy。
-
真正的 Dummy 是接口或基类的衍生,且完全不包含实现。
解决问题的层次:为了能编译通过, 我需要依赖被满足。
-
Dummy 的进一步发展。
-
Stub 是接口或基类的最低限度实现。
-
一般的,返回值是 Void 的方法不包含任何实现。
-
包含返回值的方法通常会直接返回硬编码的值。
解决问题的层次:为了能正常运行, 我希望依赖的实现不要出错。
-
不更改测试方法的调用行为,但是记录方法调用
-
Spy 类似 Stub ,但除了提供客户端可叫用成员的实例。
-
Spy 还会记录调用了哪些成员,以便单元测试验证所调用的成员是否如期调用。
解决问题的层次:为了能验证测试是否按照预期调用了成员。
-
关注调用的行为本身
-
Mock 是由 Mock 链接库动态建立 ( 其他通常是由测试开发人员使用程序代码来产生 ) 。
-
测试开发人员永远看不到实现接口或基类的实际程序代码,但是可以设定 Mock 以提供传回值、预期要调用的特定成员等等。
-
视其中的设定而定, Mock 的行为可能会像 Dummy 、 Stub或 Spy 。
解决问题的层次:在无法方便的观测系统状态变化而做出断言时, 我希望可以退而求其次, 能够得知SUT(System Under Test)正确的与外部依赖进行了交互。
-
Fake 包含轻量级的实现,通常处理它继承的类型的不同成员之间的交互。
-
虽然不是完整的产品实现,但 Fake 与产品实现很相似,尽管它会采取一些快捷方式。
解决问题的层次:为了覆盖到真实场景下的用例, 我需要依赖能够模拟真实场景下的行为, 并且我可以在不同的测试用例下指定不同的行为。
事实上,在实际使用中,这些测试替身常常会混合使用。
代码中的示例仅作为例子使用,在实际完成需求过程中,不一定会采用其中的方式 大家只需要理解测试替身想要做的工作即可,而不用过于计较其中例子的实现方式 和工作逻辑。
谢谢。