例如,这句话的意思是什么?
与外部 API 集成几乎是任何现代 Web 应用程序的保证。为了有效地测试这种集成,您需要将其 票根出来。一个好的 票根应该很容易创建,并且能够持续更新实际的、当前的 API 响应。在本文中,我们将概述使用 存根作为外部 API 的测试策略。
在此上下文中,票根意味着模拟实现。
也就是说,一个符合接口并用于测试的简单、伪造的实现。
您还有一个非常好的测试框架来创建这样的存根。 我最喜欢的是 莫基托还有 EasyMock和其他... 但 Mockito 是伟大的,你应该读它-非常优雅和强大的包
存根是 现有受养人(或协作者)的可控替代品 通过使用存根,您可以在不使用 直接处理依赖关系。
对外依赖性-现有依赖性: 您的代码是系统中的一个对象 在测试下与你无法控制的交互作用 例如文件系统、线程、内存、时间等等。)
下面代码中的例子:
public void Analyze(string filename) { if(filename.Length>8) { try { errorService.LogError("long file entered named:" + filename); } catch (Exception e) { mailService.SendEMail("admin@hotmail.com", "ErrorOnWebService", "someerror"); } } }
您想要测试 发送邮件()方法,但是要做到这一点,您需要在您的测试方法中模拟 例外,所以您只需要创建一个 Fake Stub 错误服务对象来模拟您想要的结果,然后您的测试代码将能够测试 发送邮件()方法。正如您所看到的,您需要模拟来自另一个 Dependency 的结果,这个 Dependency 是 错误服务类对象(现有 Dependency 对象)。
外行人的术语,它是虚拟数据(或假数据,测试数据等) ,您可以使用它来测试或开发您的代码,直到您(或另一方)准备好呈现/接收真实数据。这是程序员的“ Lorem Ipsum”。
员工数据库还没准备好? 用无名氏、无名氏等编一个简单的数据库。 API 还没准备好? 通过创建一个包含假数据的静态.json 文件来创建一个假的 API。
存根是一个函数定义,它具有正确的函数名、正确的参数数目和正确类型的虚拟结果。
它有助于编写测试,并作为一种脚手架,使得甚至在功能设计完成之前就可以运行示例
在这个上下文中,“ stub”一词被用来代替“ mock”,但是为了清晰和精确,作者应该使用“ mock”,因为“ mock”是一种存根,但是用于测试。为了避免美国圣约瑟的兽迷大会Further Confusion,我们需要定义什么是存根。
在一般情况下,存根是一段程序(通常是一个函数或对象) ,它封装了调用另一个程序的复杂性(通常位于另一台机器、 VM 或进程上——但不总是,它也可以是一个本地对象)。因为要调用的实际程序通常不在相同的内存空间上,所以调用它需要很多操作,比如寻址、执行实际的远程调用、编组/序列化要传递的数据/参数(与潜在的结果相同) ,甚至可能处理身份验证/安全性,等等。请注意,在某些上下文中,存根也称为代理(如 Java 中的动态代理)。
模拟是一种非常特殊且限制性很强的存根,因为模拟是用于测试的另一个函数或对象的替代品。在实践中,我们经常使用模拟作为本地程序(函数或对象)来替换测试环境中的远程程序。在任何情况下,模拟都可以在受限制的上下文中模拟被替换程序的实际行为。
当需要调用远程过程(< a href = “ https://en.wikipedia.org/wiki/Remote _ process _ call”rel = “ noReferrer”> RPC )或远程对象(一个 href = “ https://docs.oracle.com/javase/lessons/RMI/index.html”rel = “ noReferrer”> RMI 、 一个 href = “ https://en.wikipedia.org/wiki/Common _ Object _ Request _ Broker _ Architecture”rel = “ norefrer”> CORBA )时,最著名的存根类型显然是用于分布式编程的。大多数分布式编程框架/库都会自动生成存根,这样您就不必手动编写它们。存根可以从接口定义中生成,比如用 IDL编写的接口定义(但是您也可以使用任何语言来定义接口)。
通常,在 RPC、 RMI、 CORBA 等等中,我们可以区分出 客户端存根和 服务器端存根,前者主要负责封送/序列化参数并执行远程调用,后者主要负责解封送/反序列化参数并实际执行远程函数/方法。显然,客户端存根位于客户端,而服务器存根(通常称为骨架)位于服务器端。
在处理对象引用时,编写好的高效和通用存根变得相当具有挑战性。大多数分布式对象框架(如 RMI 和 CORBA)都处理分布式对象引用,但是大多数程序员在 REST 环境中都会避免这种情况。通常,在 REST 环境中,JavaScript 程序员使用简单的存根函数来封装 AJAX 调用(JSON.parse和 JSON.stringify支持对象序列化)。斯威格 · 科德根项目为以各种语言自动生成 REST 存根提供了广泛的支持。
JSON.parse
JSON.stringify
这个短语几乎可以肯定地类比于房屋建设的一个阶段ーー“把水管堵死”。在施工期间,当墙壁仍然是开放的,粗糙的管道是投入。这是继续施工的必要条件。然后,当周围的一切都准备好了,一个人回来,并添加水龙头和马桶和实际的最终产品的东西。(参见例子 如何安装水管插头。)
当您在编程中“存根”一个函数时,您构建了足够多的函数来处理(用于测试或编写其他代码)。然后,您稍后返回并用完整的实现替换它。
RPC 存根
来源
“删除一个函数意味着你只需要编写足够的代码来显示函数已被调用,而将细节留待以后有更多的时间处理。”
来自: SAMS 自学 C + + ,Jesse Liberty 和 Bradley Jones
存根是在 RPC (远程过程调用)期间转换参数的一段代码。由于客户机和服务器使用不同的地址空间,必须转换 RPC 的参数。Stub 执行此转换,以便服务器将 RPC 视为本地函数调用。
存根可以说是原始函数的 < strong > 假冒的替代品 ,它提供输出,由于以下原因,现在无法访问:
存根上有:
为什么使用存根? 在测试等环境中无法访问函数时,或其实现不可用时。
例如: 假设您想测试一个函数,其中有一个网络调用。在测试代码时,您不能等待测试的网络调用结果。因此,编写网络调用的模拟输出并继续进行测试。
TestFunction(){ // Some things here // Some things here var result = networkCall(param) // something depending on the result }
这个 networkCall 给出的结果是一个字符串,因此您必须创建一个具有完全相同参数的函数,并且它应该给出字符串输出。
String fakeNetworkCall(int param){ if(param == 1) return "OK"; else return "NOT OK"; }
现在您已经编写了一个假函数,请在代码中使用它作为替换
TestFunction(){ // Some things here // Some things here var result = fakeNetworkCall(param) // something depending on the result }
这个 fakeNetworkCall是存根。
fakeNetworkCall