”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 模拟与存根:了解主要区别

模拟与存根:了解主要区别

发布于2024-11-07
浏览:954

Mock vs Stub: Understanding the Key Differences
在软件测试中,模拟与存根是两种流行的测试替身类型,用于模拟依赖关系。它们通过在测试期间用受控替代品替换真正的依赖项来帮助隔离组件的行为。虽然模拟和存根都有类似的用途,但根据测试场景的类型,它们的使用方式有所不同。
本文深入探讨了模拟和存根之间的主要区别、它们的用例以及何时在测试策略中使用它们。

什么是测试替身?
测试替身是测试期间用于代表真实依赖项的任何对象或组件的通用术语。目标是隔离被测组件并消除可能影响测试结果的外部因素。模拟和存根是两种类型的测试替身,通常用于单元和集成测试。

什么是存根?
存根是一个测试替身,当被测试的组件调用时,它返回预定义的数据。当被测试的组件需要来自依赖项的输入,但依赖项的实际行为与测试结果无关时,通常使用它。存根提供受控响应,使您可以只关注组件内部的逻辑。

存根示例:
假设您正在测试支付处理功能。您无需调用真正的支付网关,而是使用始终返回“支付成功”响应的存根,确保可以独立测试函数中的逻辑。

const paymentGatewayStub = {
  processPayment: () => "payment successful"
};

function processOrder(paymentService) {
  const result = paymentService.processPayment();
  return result === "payment successful" ? "Order Complete" : "Order Failed";
}

// Test
console.log(processOrder(paymentGatewayStub));  // Output: "Order Complete"

在这种情况下,存根确保外部服务始终返回预期的输出,从而更容易测试内部逻辑。

什么是模拟?
模拟是一个测试替身,它不仅提供假数据,还验证组件之间的交互。模拟有助于确保使用正确的参数调用正确的方法,并确保在执行期间发生所需的事件顺序。当组件的行为或交互对测试很重要时,通常使用它们。
模拟示例:
使用相同的付款示例,假设您想要验证 processPayment() 方法在订单处理期间仅被调用一次。

const paymentGatewayMock = {
  processPayment: jest.fn().mockReturnValue("payment successful")
};

function processOrder(paymentService) {
  paymentService.processPayment();  
}

// Test
processOrder(paymentGatewayMock);
expect(paymentGatewayMock.processPayment).toHaveBeenCalledTimes(1);

在这种情况下,模拟通过检查方法是否被调用来验证交互,确保组件在执行过程中行为正确。
模拟和存根之间的主要区别
方面模拟存根
目的 验证组件之间的交互 ​​提供预定义的响应
行为 验证方法调用和参数 仅返回静态数据
使用场景 交互重要时使用 数据输出足够时使用
复杂性 实施起来更复杂 创建起来更简单
测试验证方法调用示例 具有固定响应的测试逻辑

何时使用存根
• 测试简单逻辑:当您只需要控制依赖项的输出时,请使用存根。
• 数据驱动测试:如果重点是测试组件在特定数据下的行为方式,则存根更合适。
• 示例用例:如果您正在测试需要数据库中的用户数据的登录功能,请使用存根返回虚拟用户,而不调用真实数据库。
何时使用模拟
• 基于交互的测试:如果重点是确保使用正确的参数调用正确的方法,请使用模拟。
• 测试复杂的交互:模拟非常适合与多个服务或API 交互的组件。
• 示例用例:如果您正在测试电子邮件发送服务,请使用模拟来验证是否使用预期的收件人和消息调用了 sendEmail() 函数。
模拟和存根可以一起使用吗?
是的,在某些情况下,模拟和存根在同一测试中一起使用,以实现交互验证和受控响应。例如,您可以使用存根返回特定数据,并使用模拟来验证是否调用了特定服务。
模拟和存根的优点和缺点
存根的优点:
• 简单且易于实施
• 对于单独测试组件逻辑很有用
存根的缺点:
• 无法验证方法调用或参数
• 仅限于静态响应
模拟的优点:
• 验证行为、交互和序列
• 对于具有多个依赖关系的复杂场景很有用
模拟的缺点:
• 需要更多设置并且可能使测试更难以阅读
• 如果使用不小心,可能会导致脆弱的测试
模拟与存根:您应该使用哪一个?
• 如果您的测试依赖于依赖项的输出并且您想要控制该输出,请使用存根。
• 如果您需要验证方法是否被调用或验证组件之间的交互,请使用模拟。
• 对于单元测试,更常用存根,因为重点是测试内部逻辑。
• 对于集成测试,在验证系统不同部分如何交互时,模拟更有用。

结论
模拟和存根在测试策略中都发挥着重要作用,但各自有不同的目的。存根控制依赖项返回的数据,而模拟则确保组件之间发生正确的交互。了解何时以及如何使用每种方法可以提高测试质量,从而获得更可靠的软件。通过正确应用模拟和存根,团队可以减少错误、加快开发速度,并为单元测试和集成测试创建更好的测试策略。

版本声明 本文转载于:https://dev.to/keploy/mock-vs-stub-understanding-the-key-differences-1e36?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 为什么我的 Java 项目找不到“tools.jar”?
    为什么我的 Java 项目找不到“tools.jar”?
    Java项目中缺少Tools.jar在复杂的Java编程中,您可能会遇到“无法找到tools.jar”的神秘问题“ 错误。当您的项目缺少编译和执行所必需的关键组件时,通常会出现此错误。诊断难题检查错误消息后,您会发现系统正在运行无法在预期位置找到“tools.jar”文件:C:\Program Fi...
    编程 发布于2024-11-07
  • 我什么时候应该在数据库系统中使用 MySQL BLOB 进行文件管理?
    我什么时候应该在数据库系统中使用 MySQL BLOB 进行文件管理?
    何时利用 MySQL BLOB 进行文件管理在数据库管理中,处理文件存储时,出现两个主要选项:文件系统存储或 MySQL BLOB(二进制大型)对象)存储。每种方法都有其优点和局限性,但选择最佳方法取决于应用程序的具体要求。性能注意事项在某些情况下,使用 BLOB 可以显着提高性能。当同时从多个服务...
    编程 发布于2024-11-07
  • 如何在 Java 中转义特殊字符以实现精确的正则表达式匹配?
    如何在 Java 中转义特殊字符以实现精确的正则表达式匹配?
    转义特殊字符以实现最佳正则表达式匹配使用正则表达式 (regex) 匹配文本时,转义某些特殊字符至关重要,以确保它们被解释为文字而不是元字符。在Java中,必须转义的特殊字符包括:。 [ ] { } ( ) \ < > * - = ! ? ^ $ |但是,需要注意一些例外情况:方括号 ([]) 内只...
    编程 发布于2024-11-07
  • 用 Java 构建旋转排序数组搜索:了解枢轴搜索和二分搜索
    用 Java 构建旋转排序数组搜索:了解枢轴搜索和二分搜索
    什么是旋转排序数组? 考虑一个排序数组,例如: [1, 2, 3, 4, 5, 6] 现在,如果这个数组在某个枢轴处旋转,比如在索引 3 处,它将变成: [4, 5, 6, 1, 2, 3] 请注意,数组仍然是排序的,但它被分为两部分。我们的目标是有效地在此类数组中搜索目标值。 ...
    编程 发布于2024-11-07
  • 在 � 中学习 Three.js
    在 � 中学习 Three.js
    I had the chance to dive into some web development where I wanted to add interactive 3D elements that could move and react to certain triggers. Natura...
    编程 发布于2024-11-07
  • 网站时间数据集
    网站时间数据集
    您好,我在kaggle上发现了一个网站使用时间的数据集,所以我想找到访问页面数与网站总时间之间的比率。 您可以在我的github中找到数据集和代码:https://github.com/victordalet/Kaggle_analysis/tree/feat/website_traffic ...
    编程 发布于2024-11-07
  • 简单异常示例
    简单异常示例
    该示例展示了如何监控和捕获异常。 尝试访问数组边界之外的索引会生成 ArrayIndexOutOfBoundsException。 程序故意引发此异常并捕获它。 要监视异常的代码放在 try 块内。 当发生异常时,抛出异常并被catch块捕获,结束try块。 控制权不是“叫”来捕捉的,而是自动转移...
    编程 发布于2024-11-07
  • 模板文字可以真正重用吗?
    模板文字可以真正重用吗?
    模板文字:复兴重用ES6 中的模板文字经常被吹捧为强大的文本操作工具,但一个棘手的问题仍然存在:它们真的可以重用吗?无法实现的期望乍一看,模板文字似乎只在声明时承诺动态替换。这就引出了一个问题:什么是保持静态的模板?打破循环与流行的看法相反,模板文字可以使用函数通过运行时替换来重新焕发活力构造函数作...
    编程 发布于2024-11-07
  • 在 Java 中使用 Fisher-Yates 算法对数组进行洗牌
    在 Java 中使用 Fisher-Yates 算法对数组进行洗牌
    介绍 在计算机科学领域,对元素数组或列表进行洗牌是一种常见的操作,可用于各种应用程序,从随机化游戏结果到分发牌组中的纸牌。为此目的最有效的算法之一是 Fisher-Yates Shuffle,也称为 Knuth Shuffle。该算法确保数组的每个排列都有相同的可能性,这使其成为创...
    编程 发布于2024-11-07
  • 我作为全栈开发人员的旅程:与 MERN Stack 一起成长的一年
    我作为全栈开发人员的旅程:与 MERN Stack 一起成长的一年
    你好!我是 Shivaji Zirpe,一位充满热情的全栈开发人员,专门研究 MERN 堆栈。在过去的一年里,我深入研究了 Web 开发领域,广泛使用了 React、Node.js、MongoDB 等。在这篇文章中,我想分享我的旅程、经历以及我作为开发人员的成长过程。 ?我的经历一览...
    编程 发布于2024-11-07
  • 什么是 FHIR?
    什么是 FHIR?
    介绍 与 fhir 相关的存储库列表 - Awesome-fhir 快速医疗保健互操作性资源 FHIR 服务器是一款强大的工具,彻底改变了医疗保健行业。 它充当访问和交换关键医疗数据的网关,实现不同系统和组织之间的无缝互操作性。 什么是 FHIR 服务器? FHI...
    编程 发布于2024-11-07
  • 为什么常量引用可以延长 C++ 中临时变量的生命周期?
    为什么常量引用可以延长 C++ 中临时变量的生命周期?
    通过常量引用扩展右值生命周期在 C 中,常量引用不仅充当不可变别名,还可以延长临时变量的生命周期。为什么 C 委员会决定实现此行为?此功能的一个基本原理是隐藏类和函数的实现细节。考虑一个可以返回行向量或列向量的矩阵类。为了优化性能,类可以选择根据其行优先或列优先组织返回对内部值的引用。通过要求客户端...
    编程 发布于2024-11-07
  • 如何在 Go 中将切片作为可变参数传递?
    如何在 Go 中将切片作为可变参数传递?
    将解压的切片作为可变参数传递在 Go 中,可变参数函数接受不定数量的特定类型的参数。将切片的切片传递给此类函数时,了解所涉及的类型转换和解包机制至关重要。如果切片包含与可变参数参数类型相同的元素,则可以在不使用切片的情况下传递切片拆包。然而,如果切片中包含多种类型的混合或切片中包含切片,则情况会变得...
    编程 发布于2024-11-07
  • 使用 TypeScript 和语义版本控制创建并发布 npm 库
    使用 TypeScript 和语义版本控制创建并发布 npm 库
    ?编写并发布最少的代码 要在 npm 上发布库,您需要: 一个npm 帐户;您可以在这里注册。 您的代码作为一个项目;即,您的代码目录中有一个 package.json,其中指定了名称和版本。请注意,您可以通过以下方式生成此文件: npm init 项目中的index.js。请记住...
    编程 发布于2024-11-07
  • 如何将包含的 PHP 脚本的值返回到主脚本?
    如何将包含的 PHP 脚本的值返回到主脚本?
    从包含的 PHP 脚本返回在 PHP 中,return() 函数通常用于退出脚本或函数。但是,它不能用于从包含的脚本返回到主脚本。要从包含的脚本返回并恢复主脚本中的执行,请考虑使用以下技术: 1.使用输出缓冲:在包含的脚本内,使用 ob_start() 将要返回的输出存储在变量中。然后,在主脚本中,...
    编程 发布于2024-11-07

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3