编程中的“存根”是啥意思?

Posted

技术标签:

【中文标题】编程中的“存根”是啥意思?【英文标题】:What does "to stub" mean in programming?编程中的“存根”是什么意思? 【发布时间】:2012-04-04 09:21:40 【问题描述】:

例如,这句话是什么意思?

与外部 API 集成几乎是任何现代网络应用程序的保证。为了有效地测试这种集成,您需要存根它。一个好的 stub 应该易于创建,并且始终与实际的当前 API 响应保持同步。在这篇文章中,我们将概述使用 stubs 对外部 API 的测试策略。

【问题讨论】:

你看过What is a "Stub"?接受的答案了吗? 【参考方案1】:

存根是现有依赖项(或合作者)的可控替代品 在系统中。通过使用存根,您可以在没有 直接处理依赖关系。

外部依赖 - 现有依赖: 它是您系统中的一个对象,您的代码 under test 与您无法控制的交互。 (常见的 例如文件系统、线程、内存、时间等等。)

例如下面的代码:

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");
            
        
    

你想测试 ma​​ilService.SendEMail() 方法,但是你需要在你的测试方法中模拟一个 Exception,所以你只需要创建一个Fake Stub errorService 对象来模拟您想要的结果,然后您的测试代码将能够测试 ma​​ilService.SendEMail() 方法。如您所见,您需要模拟来自另一个依赖项的结果,该依赖项是 ErrorService 类对象(现有依赖项对象)。

【讨论】:

英文?什么是现有依赖项? @Jwan622 用外行的话来说:代码使用的任何东西。如果您重新阅读并将“依赖项”替换为“类”或“功能”或其他任何内容(取决于您的背景),这可能有助于理解。有时使用现有的类/函数不是一个可行的选择,您需要一个存根(例如,在依赖于环境的函数的自动化单元测试中,例如系统的当前日期和时间)。【参考方案2】:

stub,在此上下文中,表示模拟实现。

也就是说,一个符合接口并用于测试的简单假实现。

【讨论】:

Martin Fowler 在著名的Mocks Aren't Stubs 文章中提供了更多详细信息:“但我经常看到模拟对象描述不佳。特别是我看到它们经常与存根混淆 - 一个常见的帮助测试环境。”。【参考方案3】:

通俗地说,在您(或另一方)准备好呈现/接收真实数据之前,您可以使用它来测试或开发代码的虚拟数据(或假数据、测试数据等)。这是程序员的“Lorem Ipsum”。

员工数据库还没准备好?与 Jane Doe、John Doe 等组成一个简单的组合。 API 还没准备好?通过创建一个包含假数据的静态 .json 文件来制作一个假的。

【讨论】:

谢谢你的例子:)【参考方案4】:

在这个上下文中,“stub”这个词是用来代替“mock”的,但是为了清楚和精确起见,作者应该使用“mock”,因为“mock”是一种stub,但是供测试用。为避免进一步混淆,我们需要定义什么是存根。

在一般情况下,存根是一段程序(通常是函数或对象),它封装了调用另一个程序(通常位于另一台机器、VM 或进程上)的复杂性——但并非总是如此,它也可以是一个本地对象)。因为要调用的实际程序通常不在同一个内存空间上,所以调用它需要许多操作,例如寻址、执行实际的远程调用、编组/序列化要传递的数据/参数(与潜在结果相同),甚至可能处理身份验证/安全性等等。请注意,在某些情况下,存根也称为代理(例如 Java 中的动态代理)。

模拟是一种非常具体和限制性的存根,因为模拟是用于测试的另一个函数或对象的替代品。在实践中,我们经常使用 mocks 作为本地程序(函数或对象)来替换测试环境中的远程程序。在任何情况下,模拟都可以模拟被替换程序在受限上下文中的实际行为。

最著名的存根类型显然是用于分布式编程,当需要调用远程过程(RPC)或远程对象(RMI CORBA)。大多数分布式编程框架/库会自动生成存根,因此您不必手动编写它们。存根可以从接口定义中生成,例如用IDL 编写(但您也可以使用任何语言来定义接口)。

通常,在 RPC、RMI、CORBA 等中,可以区分 客户端存根,它主要负责编组/序列化参数和执行远程调用,以及 服务器端存根,主要负责解组/反序列化参数并实际执行远程函数/方法。显然,客户端存根位于客户端,而服务器存根(通常称为骨架)位于服务器端。

在处理对象引用时,编写高效且通用的存根变得非常具有挑战性。大多数分布式对象框架(如 RMI 和 CORBA)都处理分布式对象引用,但大多数程序员在 REST 环境中避免这样做。通常,在 REST 环境中,javascript 程序员制作简单的存根函数来封装 AJAX 调用(JSON.parseJSON.stringify 支持对象序列化)。 Swagger Codegen 项目为自动生成各种语言的 REST 存根提供了广泛的支持。

【讨论】:

【参考方案5】:

Stub 是一个函数定义,它具有正确的函数名称、正确的参数数量并产生正确类型的虚拟结果。

它有助于编写测试并充当一种脚手架,即使在功能设计完成之前也可以运行示例

【讨论】:

【参考方案6】:

这句话几乎可以肯定是与房屋建设阶段的类比——“拔管”管道。在施工过程中,在墙壁仍然敞开的情况下,将粗管道放入。这是继续施工所必需的。然后,当周围的一切都准备就绪时,一个人回来并添加水龙头和马桶以及实际的最终产品。 (例如参见How to Install a Plumbing Stub-Out。)

当你在编程中“存根”一个函数时,你构建了足够多的函数来解决问题(用于测试或编写其他代码)。然后,您稍后再回来并用完整的实现替换它。

【讨论】:

【参考方案7】:

您还有一个非常好的测试框架来创建这样的存根。 我最喜欢的一个是Mockito 还有EasyMock 和其他...但是 Mockito 很棒,你应该阅读它 - 非常优雅和强大的包

【讨论】:

【参考方案8】:

RPC 存根

基本上,客户端存根是一个过程,它在客户端看来就像是一个可调用的服务器过程。 服务器端存根将服务器视为调用客户端。 客户端程序认为它正在调用服务器;事实上,它正在调用客户端存根。 服务器程序认为它是由客户端调用的;实际上,它是由服务器存根调用的。 存根相互发送消息以使 RPC 发生。

Source

【讨论】:

【参考方案9】:

“删除一个函数意味着您只需编写足以表明该函数已被调用的内容,而将细节留到以后有更多时间时。”

来自:SAMS 自学 C++、Jesse Liberty 和 Bradley Jones

【讨论】:

【参考方案10】:

Stub是一段在RPC(远程过程调用)过程中转换参数的代码。RPC的参数必须转换,因为客户端和服务器使用不同的地址空间。存根执行此转换,以便服务器将 RPC 视为本地函数调用。

【讨论】:

【参考方案11】:

存根可以说是原始函数的假替代,它提供输出,由于以下原因,现在无法访问:

暂时没有开发 不能从当前环境调用(可能正在测试)

存根有:

参数的确切数量 准确的输出格式(不一定是正确的输出)

为什么要使用存根? 当函数在测试等环境中无法访问,或者当它的实现不可用时。

示例: 假设你想测试一个有网络调用的函数。在测试代​​码时,您不能等待网络调用的结果来进行测试。所以你写了一个网络调用的模拟输出并继续你的测试。

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 是一个存根。

【讨论】:

以上是关于编程中的“存根”是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

编程中的“原子”是啥意思?

编程中的“ad hoc”是啥意思?

Windows中的Shell编程 Shell指的是啥意思?

C语言编程中的字体颜色是啥意思

FLAG1在编程中是啥意思

c编程中的init函数怎么用?是啥意思?