C/C++生态工具链——接口模拟工具gmock
一,Mock介绍
Mock是单元测试中常见的测试方式,一般用来模拟一个工具类或者第三方接口的实现方式。基于Mock编写的测试代码可以独立运行,不需要依赖工具类或者第三方接口的具体实现。
二,Mock的使用场景
当项目所依赖的某个接口函数没有被开发出来时,为了不阻塞开发进度,可以使用Mock去模拟这个接口函数的功能。
三,gmock简介
gmock的全称是Google Mock,是Google于2008年推出的C++测试工具,gmock是编写和使用C++模拟类的框架。gmock一开始是独立维护的,后面被集成进了gtest(GoogleTest),成为gtest的一个子模块,安装了gtest后就可以开始使用gmock。
gmock可以快速轻松地定义模拟对象,模拟对象提供与真实对象相同的接口。gmock允许开发者定义模拟对象的行为,例如调用哪些方法,以什么顺序,调用多少次,传哪些参数,返回什么样的值等等。
四,gmock的主要特性
1.提供了用于定义模拟行为的声明性语法。
2.支持对任意类型的函数或被重载的函数进行模拟。
3.拥有丰富的匹配器,用于验证函数参数。
4.使用了直观的语法来描述被模拟的行为。
五,如何获取gmock
获取gmock,需要下载并编译GoogleTest开源库的源代码:
git clone https://github.com/google/googletest
cd googletest
git checkout release-1.12.1 #切换到最新的版本分支
mkdir build
cd build
cmake .. #开始构建和编译
make install #编译后安装
编译结果,生成gtest和gmock的静态库:
六,gmock开发步骤
测试之前:
确定需要模拟的类接口
定义Mock类,并继承需要被模拟的类
利用MOCK_METHOD宏来模拟虚函数
测试期间:
使用testing命名空间
实例化Mock类,创建模拟对象
设置模拟对象的默认行为或期望行为(ON_CALL, EXPECT_CALL)
运行代码,检查是否与预期相符
注意:Mock更强调的是依赖的接口如何返回,而不是依赖的具体实现。
七,gmock的一些语法
a.MOCK_METHOD宏的用法:
class MyMock {
public:
MOCK_METHOD(ReturnType, MethodName, (Args...));
MOCK_METHOD(ReturnType, MethodName, (Args...), (Specs...));
};
前3个参数包含:
函数返回类型,函数名,函数传参。
第4个参数(Specs)为限定符:
const——重写const方法时需要带上
override——覆盖virtual方法时需要带上
noexcept——重写noexcept方法时需要带上
b.定义预期行为,EXPECT_CALL为例:
EXPECT_CALL(mock_object, method(matcher1, matcher2, ...))
.With(multi_argument_matcher)
.Times(cardinality)
.InSequence(sequences)
.After(expectations)
.WillOnce(action)
.WillRepeatedly(action)
.RetiresOnSaturation();
mock_object:创建的mock类对象
method:被模拟的虚函数
Times(cardinality):method运行次数
InSequence(sequences):method被执行的顺序(优先级)
WillOnce(action):method被调用一次时所产生的行为,比如该方法被调用一次返回什么值
WillRepeatedly(action):缺省/重复行为
代码样例:
using ::testing::Return;
...EXPECT_CALL(turtle, GetX())
.Times(5)
.WillOnce(Return(100))
.WillOnce(Return(150))
.WillRepeatedly(Return(200));
具体含义:
turtle对象的GetX()方法将被调用五次,第一次返回100,第二次返回150,然后每次返回200。
八,gmock使用案例
//step.01: 确认需要被模拟的类:Foo
class Foo {
public:
virtual ~Foo();
virtual int GetSize() const = 0;
virtual string Describe(const char* name) = 0;
virtual string Describe(int type) = 0;
virtual bool Process(Bar elem, int count) = 0;};
//step.02: 基于Foo,创建模拟类MockFoo
#include "gmock/gmock.h"
class MockFoo:public Foo{
public:
MOCK_METHOD(int, GetSize, (), (const, override));
MOCK_METHOD(string, Describe, (const char* name), (override));
MOCK_METHOD(string, Describe, (int type), (override));
MOCK_METHOD(bool, Process, (Bar elem, int count), (override));
//step.03: 初始化模拟类,定义预期行为,编写测试样例
using::testing::Return;
TEST(BarTest, DoesThis) {
MockFoo foo;
EXPECT_CALL(foo, Describe(5))