正如投票最多的答案所提到的,马丁·福勒(Martin Fowler)在“ 莫克斯不是存根”中讨论了这些区别,特别是副标题“莫克斯与存根之间的区别”。,因此请务必阅读该文章。
而不是着眼于如何这些东西都是不同的,我认为这是更具启发专注于为什么这些是不同的概念。每种存在的目的都不相同。
假货
一个假的是一个执行,其行为“自然”,而不是“真实的”。这些都是模糊的概念,因此不同的人对使事情变得假的有不同的理解。
伪造品的一个例子是内存数据库(例如,在:memory:
商店中使用sqlite )。您永远不会将其用于生产(因为数据不会持久保存),但是它完全可以用作测试环境中的数据库。它也比“真实”数据库轻巧得多。
再举一个例子,也许您在生产中使用了某种对象存储(例如Amazon S3),但是在测试中,您可以将对象简单地保存到磁盘上的文件中。那么您的“保存到磁盘”实现将是假的。(或者您甚至可以通过使用内存文件系统来伪造“保存到磁盘”操作。)
第三个示例,想象一个提供缓存API的对象。一个实现正确接口但根本不执行任何缓存但始终返回缓存未命中的对象将是一种伪造。
伪造的目的不是影响被测系统的行为,而是简化实现测试(通过删除不必要的或重量级的依赖项)。
存根
一个存根的行为方式“不自然”的实现。它已预先配置(通常是通过测试设置)以响应具有特定输出的特定输入。
存根的目的是使被测系统进入特定状态。例如,如果您正在为与REST API交互的某些代码编写测试,则可以存根出的REST API与API,它总是返回一个罐头回应,或者回应给特定错误的API请求。这样,您可以编写测试来断言系统对这些状态的反应。例如,如果API返回404错误,则测试用户获得的响应。
通常仅将存根实现为仅响应您已告诉其响应的确切交互。但是,使某事存根的关键特征是它的目的:存根就是建立测试用例。
cks
一个模拟类似于存根,但验证自动加入。一个模拟的目的是为了让你的测试系统如何与依赖互动的断言。
例如,如果您正在为将文件上传到网站的系统编写测试,则可以构建一个模拟接受文件文件,并可以使用该文件断言上传的文件是正确的。或者,在较小的规模上,通常使用对象的模拟来验证被测系统是否调用了模拟对象的特定方法。
模拟是与交互测试联系在一起的,交互测试是一种特定的测试方法。喜欢测试系统状态而不是系统交互的人将很少使用模拟程序。
测试双打
伪造品,存根和模拟品均属于测试双打的类别。测试倍数是您在测试中使用的任何对象或系统,而不是其他对象。大多数自动化软件测试都使用某种或多种测试倍数。其他一些测试双精度类型包括伪值,间谍和I / O 黑洞。