“存根”在编程中意味着什么?

时间:2012-03-19 20:58:01

标签: api stub

例如,这句话的含义是什么?

  

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

11 个答案:

答案 0 :(得分:88)

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

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

答案 1 :(得分:87)

存根是现有依赖关系(或协作者)的可控替代品 在系统中。通过使用存根,您可以在不使用的情况下测试代码 直接处理依赖。

外部依赖 - 现有依赖关系:
系统中的对象是您的代码 在测试中与您无法控制的交互。 (共同 示例是文件系统,线程,内存,时间等。)

例如下面的代码:

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

您想测试 mailService.SendEMail()方法,但为此,您需要在测试方法中模拟异常,因此您只需要创建一个假存根 errorService 对象来模拟您想要的结果,然后您的测试代码将能够测试 mailService.SendEMail()方法。如您所见,您需要模拟来自另一个依赖项的结果,该结果是 ErrorService 类对象(现有依赖项对象)。

答案 2 :(得分:51)

Layman的术语,它可用于测试或开发代码的虚拟数据(或虚假数据,测试数据等),直到您(或另一方)为止准备好呈现/接收真实数据。它是一名程序员&#34; Lorem Ipsum&#34;。

员工数据库尚未就绪?与Jane Doe,John Doe等组成一个简单的。 API还没准备好?通过创建包含虚假数据的静态.json文件来构成虚假文件。

答案 3 :(得分:7)

在这种情况下,使用“stub”代替“mock”,但为了清晰和精确,作者应该使用“mock”,因为“mock”是一种存根,但是用于检测。为了避免进一步的混淆,我们需要定义存根是什么。

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

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

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

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

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

答案 4 :(得分:3)

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

答案 5 :(得分:1)

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

它有助于编写测试并作为一种脚手架,以便在功能设计完成之前运行示例

答案 6 :(得分:0)

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

在编程中“残存”一个函数时,您将构建足够的函数来解决(用于测试或编写其他代码)。然后,您稍后再将其替换为完整的实现。

答案 7 :(得分:0)

RPC存根

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

Source

答案 8 :(得分:0)

“残存一个函数意味着您只编写足以表明该函数已被调用的代码,而当您有更多时间时,将其细节留待以后使用。”

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

答案 9 :(得分:0)

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

答案 10 :(得分:0)

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

  • 目前尚未开发
  • 不能从当前环境调用(可能是测试)

存根有:

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

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

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

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