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

jan*_*o-m 108 api stub

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

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

Mus*_*ici 97

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

外部依赖关系 - 现有依赖关系:
系统中的一个对象是您的测试代码与您无法控制的对象进行交互.(常见的例子是文件系统,线程,内存,时间等.)

例如下面的代码:

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");
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

你想测试mailService.SendEMail()方法,但要做到这一点,你需要在测试方法中模拟一个Exception,所以你只需要创建一个Fake Stub errorService对象来模拟你想要的结果,那么你的测试代码就是能够测试mailService.SendEMail()方法.如您所见,您需要模拟来自另一个Dependency的结果,该结果是ErrorService类对象(Existing Dependency对象).

  • @ Jwan622用非专业术语:代码使用的任何东西.如果您重新阅读并将"依赖"替换为"类"或"功能"或其他任何内容(取决于您的背景),可能会有所帮助.有时使用现有的类/函数不是一个可行的选项,您需要一个存根(例如,对依赖于环境的函数进行自动单元测试,例如系统的当前日期和时间). (16认同)
  • 英语?什么是现有的依赖? (8认同)

Ode*_*ded 93

一个存根,在此背景下,意味着一个模拟实现.

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

  • 更多细节在Martin Fowler的着名[Mocks Are not Stubs](http://martinfowler.com/articles/mocksArentStubs.html)文章中提供:"但是我经常看到模拟对象描述得很差.特别是我看到他们经常与存根混淆 - 这是测试环境的常见帮手." (3认同)

Noo*_*ime 54

Layman的术语,它是虚拟数据(或假数据,测试数据等),您可以使用它来测试或开发代码,直到您(或另一方)准备好呈现/接收实际数据.这是程序员的"Lorem Ipsum".

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

  • 谢谢你的例子:) (2认同)

Lor*_*lor 8

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

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


Ren*_*lak 7

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

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

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

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

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

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


mat*_*tdm 5

这句话几乎可以肯定是与房屋建设阶段\xe2\x80\x94“拔除”管道的类比。在施工过程中,当墙壁仍然敞开时,就会安装粗糙的管道。这是施工继续进行所必需的。然后,当周围的一切都准备就绪时,人们会回来添加水龙头、马桶和实际的最终产品。(例如,请参阅如何安装管道接头。)

\n\n

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

\n


Tao*_*if7 5

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

  • 现在还没有开发出来
  • 它无法从当前环境调用(也许是测试)

存根有:

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

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

示例:
假设您要测试一个包含网络调用的函数。在测试代​​码时,您不能等待网络调用的测试结果。因此,您编写网络调用的模拟输出并继续测试。

TestFunction(){
  // Some things here

  // Some things here

  var result = networkCall(param)

  // something depending on the result
}
Run Code Online (Sandbox Code Playgroud)

这个网络调用给出了一个字符串,因此您必须创建一个具有完全相同参数的函数,并且它应该给出字符串输出。

String fakeNetworkCall(int param){
  if(param == 1) return "OK";
  else return "NOT OK";
}
Run Code Online (Sandbox Code Playgroud)

现在您已经编写了一个伪函数,请在代码中使用它作为替换

TestFunction(){
  // Some things here

  // Some things here

  var result = fakeNetworkCall(param)

  // something depending on the result
}
Run Code Online (Sandbox Code Playgroud)

fakeNetworkCall是一个存根。