MySQL Unittest实践(下 Gmock篇)

一、简介

使用Gtest基本上能够满足绝大多数的测试场景,但是对于一些涉及多个模块交互、文件系统、网络通信等复杂的场景,很难仿真一个真实的环境进行单元测试。这时就需要引入模拟对象Mock Objects来模拟程序的一部分来构造测试场景。

Google C++ Mocking框架(简称Gmock)是一个库,可以用来创建模拟类并使用它们。通过定义模拟对象来模拟这些类的行为操作,通过Gmock提供的接口,构造自己想要的返回值和行为,模拟出一切你想要在测试中需要的东西。

Gmock提供了以下特性:一是轻松地创建mock类;二是支持丰富的匹配器(Matcher)和行为(Action);三是支持丰富的期望行为的定义;四是多平台的支持。

一般的,将Gmock与Gtest搭配使用。

二、Gmock使用方法

Gmock的主要的思想是通过mock类模拟出当前已实现的功能或者未实现的功能。未实现的功能比较简单,这里不在展开,接下来主要说一下如何模拟一个已实现的功能。

2.1 基本步骤

1、使用一些简单的宏描述你想要模拟的接口,将其扩展到你的mock类的实现上;

2、创建一些模拟对象,并设置其期望和行为;

3、使用模拟对象的代码进行测试;

2.2 准备工作

准备工作主要是定义mock类以及一些宏等资源,方便后面设置模拟方法的各种选项,这里举一个简单的例子方便理解:

#include <gtest/gtest.h>
#include <gmock/gmock.h>class MockConn{
public:MOCK_METHOD2(mock_func1, int(int, char*));MOCK_METHOD0(mock_func2, char*(void));MOCK_METHOD1(mock_func3, void (float));......
}MockConn *mock = NULL;#define func1(try, ip) mock_obj->moc_func1(trx, ip)#include “path/to/file.cc”#undef func1Class MockTest:public::testing::Test{......
}

首先头文件包含同Gtest,接着定义一个mock类,mock类中要描述出你想要模拟的接口。

假如现在需要测试函数的原型为int func1(int try, char* ip);,这个函数的功能是对一个ip地址设置它的最大尝试连接次数,函数返回实际的连接的次数。

MOCK_METHOD*(mock_func_name, prototype)宏用于描述你要模拟的方法的特性,MOCK_METHOD后面的数字*表示传入参数的个数,mock_func_name表示将要用此宏来替换想要的模拟的方法,prototype为函数的原型,包括返回值的类型和传入参数的类型,不写函数名,形参名可写可不写。

接下来定义全局模拟方法对象的指针mock,然后定义宏替换mock类中的方法,这一步旨在用宏替换真正已实现的func1函数,模拟func1的返回值。后面通过#include将真正func1的实现覆盖成模拟方法mock_func1,接下来通过#undef解除宏定义,这样就可以给模拟方法设置期望行为了。

2.3 设置方法的期望行为

在Gmock中,使用EXPECT_CALL()宏来设置模拟方法的各项期望值,一般的格式为:

EXPECT_CALL(mock_object, method(matchers)).Times(cardinality).WillOnce(action).WillRepeatedly(action);

这个宏有两个参数:首先是mock对象,然后是方法及其参数。后面的参数可选,.Times(cardinality)设置预期执行的次数,.WillOnce(action)设置一次执行的行为, .WillRepeatedly(action)设置缺省/重复执行的行为。当然还可以设置其他的选项,下面重点介绍一下。

2.3.1 匹配器(Matcher

匹配器(Matcher)用于定义mock类中的方法的形参的值,检查传入参数是否符合预期设置的条件。支持各种类型的比较,比如整数比较、浮点数比较、字符串比较、容器比较等,这些匹配符都在Gmock的*::testing*这个命名空间下,使用时需要先引入这个名空间。这里列出常用的一些匹配符。

一般比较

Eq(value) 或者 value

argument == value

Ge(value)

argument >= value

Gt(value)

argument > value

Le(value)

argument <= value

Lt(value)

argument < value

Ne(value)

argument != value

IsNull()

method的形参必须是NULL指针

NotNull()

argument is a non-null pointer

Ref(variable)

形参是variable的引用

TypedEq(value)

形参的类型必须是type类型,而且值必须是value

A() or An()

任意值

浮点数的比较

DoubleEq(a_double)

形参是一个double类型,形参值近似于a_double

FloatEq(a_float)

同上,只不过类型是float

NanSensitiveDoubleEq(a_double)

形参是一个double类型,形参值近似于a_double,

NanSensitiveFloatEq(a_float)

同上,只不过形参是float

字符串匹配
这里的字符串即可以是C风格的字符串,也可以是C++风格的。

ContainsRegex(string)

形参匹配给定的正则表达式

EndsWith(suffix)

形参以suffix截尾

HasSubstr(string)

形参有string这个子串

MatchesRegex(string)

从第一个字符到最后一个字符都完全匹配给定的正则表达式.

StartsWith(prefix)

形参以prefix开始

StrCaseEq(string)

参数等于string,并且忽略大小写

StrCaseNe(string)

参数不是string,并且忽略大小写

StrEq(string)

参数等于string

StrNe(string)

参数不等于string

容器的匹配
很多STL的容器的比较都支持==这样的操作,对于这样的容器可以使用上述的ContainerEq(container)来比较。也可以使用下面的这些容器匹配方法:

Contains(e)

在method的形参中,只要有其中一个元素等于e

Each(e)

参数各个元素都等于e

ElementsAre(e0, e1, …, en)

形参有n+1的元素,并且一一匹配

ElementsAreArray(array) 或者ElementsAreArray(array, count)

和ElementsAre()类似,除了预期值/匹配器来源于一个C风格数组

ContainerEq(container)

类型Eq(container),就是输出结果有点不一样,这里输出结果会带上哪些个元素不被包含在另一个容器中

2.3.2 基数(Cardinalities)

基数(Cardinalities)用于Times()中来指定模拟函数将被调用多少次|,一般它的值设置为一个具体的数,有时可能设置在一个区间,这里介绍几个较为常用的用法:

AnyNumber()

函数可以被调用任意次.

AtLeast(n)

预计至少调用n次.

AtMost(n)

预计至多调用n次.

Between(m, n)

预计调用次数在m和n(包括n)之间.

Exactly(n) 或 n

预计精确调用n次. 特别是, 当n为0时,函数应该永远不被调用.

2.3.3 行为(Actions)

行为(Actions)用于指定mock类的方法所期望模拟的行为:比如返回什么样的值,对引用、指针赋上什么值,等等。 值的返回类型常用的有:

Return()

让Mock方法返回一个void结果

Return(value)

返回值value

ReturnNull()

返回一个NULL指针

ReturnRef(variable)

返回variable的引用.

ReturnPointee(ptr)

返回一个指向ptr的指针

另一面的作用(Side Effects)

Assign(&variable, value)

将value分配给variable

SetArrayArgument(values, values+num)

设置内部中间变量的值

使用函数或者函数对象(Functor)作为行为

Invoke(f)

使用模拟函数的参数调用f, 这里的f可以是全局/静态函数或函数对象.

Invoke(object_pointer, &class::method)

使用模拟函数的参数调用object_pointer对象的mothod方法.

复合动作

DoAll(a1, a2, …, an)

每次发动时执行a1到an的所有动作.

IgnoreResult(a)

执行动作a并忽略它的返回值. a不能返回void.

2.3.4 序列(Sequences)

默认定义的期望行为是无序(Unordered)的,但有时候需要定义有序的(Ordered)的调用方式,即序列 (Sequences) 指定预期的顺序。在同一序列里的所有预期调用必须按它们指定的顺序发生;反之则可以是任意顺序。

Sequence s1, s2;
EXPECT_CALL(mockFoo, getSize()).InSequence(s1, s2).WillOnce(Return(1));

三、编译运行

MySQL源码下的Unittest默认是不运行的,这是因为MySQL默认不带Gtest,因此想要编译运行,需要添加参数: 

一种方法是在线自动安装。在cmake的时候加 -DENABLE_DOWNLOADS=1参数,它会自动从Github下载对应版本的googletest。这是比较推荐的方法。

另一种方法是通过本地zip包安装。一般5.7.x需要的版本是release-1.8.0,如果不确定可以查看unittest/gunit/CMakeLists.txt需要的版本。然后cmake 时加-DLOCAL_GMOCK_ZIP=/path/to/gooletest-release-1.8.0.zip ,路径改为自己的路径。

Unittest提供整合编译和单独编译的两种方式。方法为在cmake时添加-DMERGE_UNITTESTS=1,1为整合编译,0为单独编译。

图1 MySQL Test Unittest测试用例执行成功的结果图

图1 MySQL Unittest测试用例执行失败的结果图

四、结束语

代码的正确性是一个程序的首要前提,会编写单元测试是每一个开发者应具备的基本技能。Gtest和Gmock是非常棒的C++单测框架,学习并灵活应用这些单测工具,可以提升软件的稳定性和健壮性,方便定位问题修复缺陷,更高效率得进行程序功能的扩展和项目代码的维护。

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

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

相关文章

【大数据】数据中台怎么样助力企业创新和客户实践

在当今数字化时代&#xff0c;数据成为了企业竞争的关键因素。企业拥有大量的数据&#xff0c;但如何高效地利用这些数据&#xff0c;实现创新和提升客户体验&#xff0c;成为了一项重要的挑战。数据中台作为一种重要的数据管理和分析工具&#xff0c;发挥着关键的作用。本文将…

Select插件的用法

文章目录 1.知识回顾2.使用方法2.1 builder属性2.2 selector属性2.3 shouldRebuild属性2.4 child属性3 示例代码我们在上一章回中介绍了组件之间共享数据相关的内容,本章回中将继续介绍该内容.闲话休提,让我们一起Talk Flutter吧。 1.知识回顾 我们在前面章回中介绍了全局共…

今年1-8月,Temu的客户量下降了25%,Shein和TikTok Shop不降反增

根据Earnest信用卡数据&#xff0c;2024年1月至8月&#xff0c;在Temu平台上交易的购物者减少了约25%&#xff0c;表明该平台的增长放缓。 自上线两年以来&#xff0c;Temu通过打折和广告策略&#xff0c;尤其是在超级碗期间投放大量广告&#xff0c;迅速扩展并广泛影响了爱好…

分享5款AI毕业论文生成系统使用教程!开题报告一键生成!

在当前的学术研究和写作领域&#xff0c;AI论文生成工具的应用越来越广泛。这些工具不仅能够提高写作效率&#xff0c;还能帮助研究人员快速生成高质量的论文内容。今天&#xff0c;我将分享五款AI毕业论文生成系统&#xff0c;并重点推荐千笔-AIPassPaper&#xff0c;帮助你高…

自动驾驶系列—DOW(开门预警):让每一次开门都更安心

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

嵌入式项目:STM32平衡车详解 (基础知识篇) (基于STM32F103C8T6)

前言&#xff1a; 本文是基于B站草履虫编写的平衡车相关内容&#xff0c;包括模块和基础知识&#xff0c;结合代码进行讲解&#xff0c;将知识进行汇总 &#xff08;由于本篇内容较长&#xff0c;请结合目录使用) 注&#xff1a;基于开源精神&#xff0c;本文仅供学习参考 目…

滑动窗口 -- 限制窗口内某元素的数量/种类

目录 长度最小的数组 题解&#xff1a; 将x减到0的最小操作数 题解&#xff1a; 最大连续1的个数 题解&#xff1a; 无重复字符的最长子串&#xff08;限制数量&#xff09; 题解&#xff1a; 水果成篮&#xff08;限制种类&#xff09; 题解&#xff1a; 找到字符串中…

Studying-图论包含的算法总结

目录 1.DFS&#xff08;深度优先搜索&#xff09; 代码框架&#xff1a; 2. BFS&#xff08;广度优先搜索&#xff09; 代码框架&#xff1a; 3. 并查集 4.最小生成树之Prim 5.最小生成树之Kruskal 6.拓扑排序 7. 最短路径之-dijkstra&#xff08;朴素版&#xff…

淘宝霸屏必备工具:淘宝商品评论电商API接口

淘宝商品评论电商API接口是指用于获取淘宝商品评论信息的一种接口&#xff0c;通过该接口可以获取淘宝网上商品的评价内容、评价等级、评价数量等信息。通过了解并使用该接口&#xff0c;能够帮助电商了解消费者对商品的评价情况&#xff0c;做好商品的推广和销售工作。 接口使…

Leetcode - 周赛416

目录 一&#xff0c;3295. 举报垃圾信息 二&#xff0c;3296. 移山所需的最少秒数 三&#xff0c;3297. 统计重新排列后包含另一个字符串的子字符串数目 I 四&#xff0c;3298. 统计重新排列后包含另一个字符串的子字符串数目 II 一&#xff0c;3295. 举报垃圾信息 本题就是…

消息号 FS215 对科目 2221010200 7333允许销项税, J1 不允许

业务场景&#xff1a; 在做发票校验时&#xff0c;报错“消息号 FS215 对科目 2221010200 7333允许销项税, J1 不允许”而且计算税额失效&#xff0c;红灯报错。 初步怀疑是税码配置问题 FTXP J1是进项税&#xff0c;但是这里维护了销项税和均一税&#xff0c;在这里删除是需…

SQLSERVER通过触发器限制客户端IP地址

方法一&#xff1a;SQL Server 2005 SP2或更高版本(触发器) 当SQL Server 2005升级到SP2或者更高的版本的时候&#xff0c;还可以通过新增的触发器来实现控制。 执行下面的T-SQL后&#xff0c;将使除IP地址为192.168.1.1之外的客户端连接失败。 USE master; GO CREATE TRIGGE…

CMA软件检测机构人员职责分类、要求、档案资料

一、CMA软件检测机构人员职责分类&#xff1a; 1、最高管理者 2、授权签字人 3、技术负责人 4、质量负责人 5、软件测试人员 &#xff08;从事软件测试项目管理、测试需求分析、测试策划和测试设计活动的人员、软件测试执行人员&#xff09; 6、报告编制员 7、报告审核…

革新体验:细数3D在线预览在多个行业的广泛应用

‌3D在线预览展示技术的应用领域非常广泛&#xff0c;涵盖了从电子商务、产品设计、建筑设计到文化遗产保护等多个方面。‌ ‌1、电子商务‌&#xff1a; 在电商领域&#xff0c;3D展示技术为商品提供了全方位的展示&#xff0c;包括产品的外观、功能和卖点。这种交互式的购物…

【Docker】01-Docker常见指令

1. Docker Docker会下载镜像&#xff0c;运行的时候&#xff0c;创建一个隔离的环境&#xff0c;称为容器。 docker run -d \ # 创建并运行一个容器&#xff0c;-d表示后台运行 --name mysql \ # 容器名称-p 3307:3306 \ # 端口映射&#xff0c;宿主机端口映射到容器端口-e TZ…

buuctf [ACTF2020 新生赛]Include

学习笔记。 开启靶机。 进入靶场&#xff1a; 我们跟进 tips瞅瞅&#xff1a; 额&#xff0c;纯小白&#xff0c;能想到的就是先F12看看&#xff0c;在CTRLu、以及抓包。 得&#xff0c;不会了&#xff0c;看wp呗&#xff0c;不会死磕没脑子0,0&#xff1f; 参考&#xff1a;…

如何在 VitePress 站点中集成 Gitalk 评论插件及其关键注意事项

你好&#xff0c;我是陈明勇&#xff0c;一名热爱技术、乐于分享的开发者&#xff0c;同时也是开源爱好者。 成功的路上并不拥挤&#xff0c;有没有兴趣结个伴&#xff1f; 个人网站&#xff1a;https://chenmingyong.cn 文章持续更新&#xff0c;如果本文能让您有所收获&#…

OJ在线评测系统 后端 用策略模式优化判题机架构

判题机架构优化(策略模式) 思考 我们的判题策略可能会有很多种 比如 我们的代码沙箱本身执行程序需要消耗时间 这个时间可能不同的编程语言是不同的 比如沙箱执行Java要额外花费2秒 我们可以采用策略模式 针对不同的情况 定义不同独立的策略 而不是把所有情况全部放在一个i…

二分图算法模板以及简单应用

染色法判断二分图 给定一个 n 个点 m 条边的无向图&#xff0c;图中可能存在重边和自环。 请你判断这个图是否是二分图。 输入格式 第一行包含两个整数 n 和 m。 接下来 m 行&#xff0c;每行包含两个整数 u 和 v&#xff0c;表示点 u 和点 v 之间存在一条边。 输出格式 …

Matplotlib | 一文搞定Matplotlib从入门到实战演练!

文章目录 1 什么是Matplotlib1.1 Matplotlib的安装1.2 Matplotlib的基本使用 2 绘制直线3 绘制折线设置标签文字和线条粗细设置中文标题风格的设置 4 绘制曲线绘制曲线yx^2绘制正弦曲线和余弦曲线画布分区 5 绘制散点图绘制不同种类不同颜色的线 6 绘制条形图&#xff08;柱状&…