在编程中“存根”是什么意思?


117

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

在任何现代Web应用程序中,几乎都可以与外部API集成。为了有效测试这种集成,您需要将其存根。一个好的存根应该易于创建,并与实际,当前的API响应保持一致。在本文中,我们将概述使用外部API 存根的测试策略。


9
您是否看过什么是“存根”中的可接受答案
尼克(Nick)

Answers:


103

存根是系统中现有依赖项(或协作者)的可控替代。通过使用存根,您可以测试代码而无需直接处理依赖项。

外部依赖关系-现有依赖关系:
这是系统中的一个对象,您的被测试代码与之交互并且不受您控制。(常见的示例是文件系统,线程,内存,时间等。)

例如下面的代码:

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()方法,但是要做到这一点,您需要在测试方法中模拟一个Exception,所以您只需要创建一个Fake Stub errorService对象来模拟您想要的结果,那么您的测试代码将是能够测试mailService.SendEMail()方法。如您所见,您需要模拟来自另一个依赖关系的结果,该另一个依赖关系是ErrorService类对象(现有依赖关系对象)。


9
英语?什么是现有依赖项?
Jwan622,2014年

17
@ Jwan622用外行术语来说:代码使用的所有内容。如果您重新阅读并将“依赖性”替换为“类”或“功能”或其他内容(取决于您的背景),可能会有所帮助。有时,使用现有的类/函数不是一个可行的选择,并且您需要存根(例如,在依赖于环境的函数(例如系统的当前日期和时间)的自动单元测试中)。
MasterMastic

101

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

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


3
Martin Fowler 在著名的Mocks Are n't Stubs文章中提供了更多详细信息:“但是,我经常看到模拟对象的描述不佳。特别是,我经常看到它们与stub混淆,stub是测试环境的常见帮助。”
pba 2015年

61

用Layman的术语来说,它是伪数据(或假数据,测试数据等),可用于测试或开发代码,直到您(或另一方)准备好呈现/接收真实数据为止。这是程序员的“ Lorem Ipsum”。

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


1
谢谢您的示例:)
CapturedTree

8

在这种情况下,用“存根”代替“模拟”,但是为了清楚和精确起见,作者应该使用“模拟”,因为“模拟”是一种存根,但用于测试。为了避免进一步的混乱,我们需要定义什么是存根。

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

模拟是一种非常特定且具有限制性的存根,因为模拟是用于测试的另一个函数或对象的替代。在实践中,我们经常将模拟程序用作本地程序(函数或对象),以替换测试环境中的远程程序。无论如何,模拟都可以在受限的上下文中模拟替换程序的实际行为。

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

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

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



3

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

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


3

这个短语几乎可以肯定地比喻为房屋建设的一个阶段-“拔出”管道。在施工过程中,当墙壁仍然打开时,将插入粗糙的管道。这对于继续施工是必要的。然后,当周围的一切准备就绪时,人们会回来并添加水龙头和马桶以及实际的最终产品。(例如,请参阅“ 如何安装管道残端”。)

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


0

RPC存根

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

资源


0

“删除一个函数意味着您将只编写足以表明该函数已被调用的信息,而在有更多时间时将其细节留给以后使用。”

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.