Test Doubles测试替身: Testing in Distributed Systems and Real World

news2024/11/18 8:19:16

什么是Test Doubles

In software testing, we developed unit tests and integration tests to test the code's functionality. However, in the real world, it is very common for a piece of code to interact with external components, for example, databases, public APIs, or other computers. n the real world with distributed computing, challenges are everywhere, systems will have to handle things like black Friday user traffic, lightning hit the data centers. To build robust software, our tests should cover all possible cases. As behaviors of external dependencies are hard to control, test doubles are introduced to replace production objects to reduce complexity and facilitate testing. Test doubles are useful not only to test unlikely events, but also isolates normal tests from the unpredictability of the real system.

"Test Doubles" 是一种用来辅助单元测试的技术,这个名字是由Gerard Meszaros首次提出的,他将其比喻为电影制作中的替身演员。当我们进行单元测试时,我们通常关注的是测试特定的函数或方法。然而,这些函数或方法常常依赖于其他的对象或系统。例如,一个函数可能需要从数据库中查询数据,或者需要调用另一个服务的API。在这种情况下,这些依赖关系可能会导致测试变得复杂或者不可预测。为了解决这个问题,我们可以使用"Test Doubles"来模拟这些依赖关系。

Types of Test Doubles

"Test Doubles"的类型主要有以下几种:Fakes, Stubs, Mocks。

Fakes

Fakes 是真实对象的简化版本。它们是完全功能性的,但是以一种更简单或者更容易控制的方式实现。例如,你可能会创建一个 Fake 的数据库,这个数据库可能只是在内存中存储数据,而不是在硬盘上。

Stubs

Stubs 是预先配置了返回数据的人工类。它们并不关心被调用了多少次或者以什么参数被调用,它们只是简单地返回预先配置的响应。例如,你可能会创建一个 Stub 的网络服务,这个服务可能总是返回固定的响应,而不管请求的内容是什么。

可以说stub比fake还要省事儿,直接预定好返回值,连装都不装了。 

Mocks

Mocks 是真实类的变种,可以进行细粒度的控制。与 Stubs 不同,Mocks 可以检查它们被调用了多少次,以及被调用时的参数是什么。Mocks 通常用于验证你的代码是否正确地与依赖关系进行交互。例如,在电子邮件服务中,我们不希望每次运行测试时都发送电子邮件。此外,在测试中验证是否发送了正确的电子邮件并不容易。我们唯一能做的就是验证 sendEmail() 方法是否被调用。我们可以为 sendEmail() 写一个 mock 方法,这个 mock 方法将帮助我们记录它是否被我们的应用程序调用。这样,我们就可以在不实际发送电子邮件的情况下,验证我们的代码是否正确地调用了发送电子邮件的方法。

使用Test Doubles的其他好处

第三方API可能出现故障并不是我们使用test doubles的唯一原因。使用测试替身还有这些好处:

  • 速度/性能:API可能很慢(网络流量、大型数据库等)。良好的测试套件能快速执行,这使得我们可以进行更多的测试场景。
  • 覆盖率高:例如API的更改,响应缓慢,超时,出错等。我们都可以通过mock模拟出来。
  • 稳定性:确保返回结果的确定性,减少测试的不稳定性。
  • 用于开发:假设我们还没有实现的功能,我们也可以先用Test double替代它,此时test double的作用就不是测试而是开发了,也未尝不可。

Java中的Test Doubles实践

1 Fakes的创建

Fakes的创建很简单也很好理解。我们其实只需要创建一个新的类,这个类应该实现与原始类相同的接口。这样子我们就有了这个“替身”来代替原始类了。然后我们在这个类写相应的工作实现,但相比原始实现,它应该更简洁、更快。

2 Stubs and Mocks的创建

创建Stubs和Mocks我们可以用一个叫Mockito的Java框架。

2.1 一个使用Mockito创建stub的例子:

// 1 - create mock object
LinkedList mockedList = mock(LinkedList.class);
// 2 - define stubbing return value before actual execution
when(mockedList.get(0)).thenReturn("first");
// 3 - call methods
// 3.1 - the following prints "first"
System.out.println(mockedList.get(0));
// 3.2 - the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));

在这个例子中我们提前定义好了如果调用get(0)就返回“first”,对于没预定义的会自动返回null。

下面是一个用回调函数创建stub的例子:

when(mock.someMethod(anyString())).thenAnswer(
    new Answer() {
        public Object answer(InvocationOnMock invocation) {
            Object[] args = invocation.getArguments();
            Object mock = invocation.getMock();
            return "called with arguments: " + Arrays.toString(args);
        }
    });

when函数可以接受一个Answer对象作为参数,这个Answer对象定义了当预期的方法被调用时,应该如何响应。这个例子中,当someMethod函数被调用时,我们返回了一个包含了所有参数的字符串。

Mockito提供了一系列的doXxx函数,比如doThrow(), doAnswer(), doNothing(), doReturn()doCallRealMethod(),这些函数可以用来代替when函数,用于定义当预期的方法被调用时的行为。

2.2 一个使用Mockito创建Mock的例子

// 1 - create mock object
List mockedList = mock(List.class);
// 2 - call methods on mock object
mockedList.add("one");
mockedList.clear();
// 3 - verify the methods are called
verify(mockedList).add("one");
verify(mockedList).clear();
// 3.1 - verify the number of times a method is called
verify(mockedList, times(1)).add("one");

我们可以看到除了验证方法是不是调用过,还可以看方法被调用的次数,这正是Mock的功能特点。在这个代码中,假设add("one")方法并没有被调用过,当你执行verify(mockedList).add("one"),Mockito 就会抛出一个异常,说明这个预期的调用并没有发生。如果add("one")方法被正确地调用过,那么verify方法就不会有任何动作,测试将继续进行。

除了times,verify还可以接受其他参数,例如,never()表示预期从未调用,atMostOnce()表示最多调用一次,atLeast(2)表示至少调用两次。如果实际的调用次数与预期不符,verify会抛出异常。

verify(mockedList, never()).add("never happened");
verify(mockedList, atMostOnce()).add("once");
verify(mockedList, atLeast(2)).add("three times");

Reference 最后附一个英文参考:

https://blog.pragmatists.com/test-doubles-fakes-mocks-and-stubs-1a7491dfa3da

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/517321.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【人工智能概论】pyplot作图中文显示、逐点坐标显示、保存图像

【人工智能概论】pyplot作图中文显示、逐点标记、保存图像 文章目录 【人工智能概论】pyplot作图中文显示、逐点标记、保存图像一. 简单的绘图二. 逐点坐标显示三. 中文显示四. 中文显示可能遇到的问题——缺少字体4.1 下载 SimHei.ttf4.2 复制 SimHei.ttf 到 Matplotlib 的 fo…

好的Robots.txt设计对Google收录有很大的帮助

Robots.txt 文件是用于指导搜索引擎爬虫在网站上爬行的标准。正确地设计 Robots.txt 文件可以帮助 Google 爬虫更好地理解您的网站结构,从而提高您的网站在 Google 搜索引擎上的收录率。 以下是一些设计 Robots.txt 文件的技巧,可以帮助 Google 爬虫更好…

security 报错:There is no PasswordEncoder mapped for the id “null“

security在登录的时候 无法登录成功 首先解读错误 下面百度翻译 安全框架设置了登录验证 说你没有密码编辑器 解决方法 一: 往容器中注册一个PasswordEncoder 解决方法二: 设置用户权限和角色的时候添加方法,加进去一个PasswordEncoder 只需要解决方案的话 下面的内容…

K8S系列之污点和容忍度详细分析

架构图 本篇文档主要介绍污点和容忍度的关系。 污点和容忍度 污点顾名思义就是脏的东西,给节点添加污点来限制pod调度到该节点上,如果pod可以容忍这种污点就可以被调度到有污点的节点上,如果不能容忍就不能被调度到该节点上。 污点作用于节…

排队领奖模式吸引新消费者,电商平台如何创新引流拓客?

在当前的电商市场中,由于竞争日趋激烈,很多电商平台产生了引流拓客缺乏新意的难题,即很难找到新的流量,并且难以把这些流量转化为消费者。在这个瞬息万变的时代,当然是谁有创意谁能吸引消费者,谁才能当道。…

Sequence-to-Sequence Knowledge Graph Completion and Question Answering

[2203.10321] Sequence-to-Sequence Knowledge Graph Completion and Question Answering (arxiv.org) 目录 1 Abstract 2 Introduction 3 KGT5 Model 3.1 Textual Representations & Verbalization 3.2 Training KGT5 for Link Prediction 3.3 Link Prediction Inf…

Inception Network

文章目录 一、Inception Network简介二、CNN的痛点三、Inception Network1. 1x1卷积核1.1 升维/降维:1.2. 调节参数数量:1.3. 增加非线性特性: 2. Inception原始模型3. Inception Module4. Inception Network 四、代码示例 一、Inception Net…

接口自动化测试 vs. UI自动化测试:为什么前者更快,更省力,更稳定?

从入门到精通!企业级接口自动化测试实战,详细教学!(自学必备视频) 目录 前言: 一、什么是接口自动化测试和 UI 自动化测试 二、为什么接口自动化测试效率比 UI 自动化测试高 1.执行速度 2.维护成本 3.…

AI人工智能与机器人的探索和应用1.1

文章来源于:https://mp.weixin.qq.com/s/fqivYVdakVKG-zDVfD4Qzg 研究机器人和人工智能的技术已有多年了,想来想去,觉得还是有必要对过往的技术做一些凝练和总结。在此过程中,除了能够将知识系统化,构建自己的知识体系…

三次输错密码后,系统是怎么做到不让我继续尝试的?

故事背景 忘记密码这件事,相信绝大多数人都遇到过,输一次错一次,错到几次以上,就不允许你继续尝试了。 但当你尝试重置密码,又发现新密码不能和原密码重复: 相信此刻心情只能用一张图形容: 虽…

python二次加工标准类型 | 包装与授权

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和…

洽洽离年轻人更近了,陈先保离百亿KPI呢?

文|螳螂观察 作者|图霖 留给陈先保实现百亿营收的时间不多了。 过去几年,洽洽凭借着在产品端、市场端、供应端的绝对实力,守住了休闲零食行业龙头的地位。但最新发布的2023年第一季度业绩报告,却出现了6年来首次营收、净利双双下降。 报告…

Excel大数据量单元格快速填充

个人简介:一个从会计转行数据分析师的三旬老汉 擅长领域:数据分析、数据仓库、大数据 博客内容:平时会将自己工作中遇到的问题进行归纳总结,分享给各位小伙伴,意在帮助大家少加班、不掉发,让我们相互学习&a…

const/static修饰成员函数+初始化列表

一、const修饰成员函数 首先,我们知道,所有的成员函数(除static修饰的),编译器都会隐式传递一个this指针。 它的默认类型为 Type* const this,即this指针只能指向最左边的第一个传入的对象。 const修饰成…

Docker容器体系结构及特点

Docker容器体系结构及特点 Docker是一个应用容器引擎,通过Docker,管理员可以非常方便地对容器进行管理。Docker基于Go语言开发,并且遵从Apache 2.0开源协议。 Docker提供了对容器镜像的打包封装功能。利用Docker,开发者可以将他…

2023 最新版IntelliJ IDEA 2023.1创建Java Web 项目详细步骤(图文详解)

文章目录 🧭 版本情况JavaIDEATomcatmaven 🌏 创建步骤🚗 1、依次点击File >> New >> Project🚓 2、选择New Project 输入自己的项目名,选择JDK版本,而后点击create进行创建🚕 3、鼠…

开新能源汽车有充电焦虑吗?2022年国内充电桩数量已达521万台

哈喽大家好,新能源汽车的不断普及使充电桩市场快速发展起来,同时充电桩的技术正在不断改进,包括充电速度、安全性、互联网功能等多个方面。相比与日渐壮大的新能源汽车用户规模,充电桩的建设相对发展速度较慢,近几年来…

网络编程代码实例:守护进程版

文章目录 前言代码仓库内容目录结构代码结果总结参考资料作者的话 前言 网络编程代码实例:守护进程版。 代码仓库 yezhening/Environment-and-network-programming-examples: 环境和网络编程实例 (github.com)Environment-and-network-programming-examples: 环境…

XShell配置以及使用教程

目录 1、XShell介绍 2、安装XShell 1. 双击运行XShell安装文件,并点击“下一步” 2. 点击“我接受许可证协议中的条款”,点击“下一步” 3. 点击“浏览”更改默认安装路径,点击“下一步” 4. 直接点击“安装” 5. 安装完成&#xff0…

C语言小游戏的实现——三子棋

前言 Hello!友友们,前边我们已经学习了C语言的基础知识,但单纯的理论和简单的代码演示是无法真正做到巩固所学的知识的,那么今天我将会带领大家,根据之前所学的知识,来写一个三子棋小游戏。 目录 前言 总…