windows从零搭建googlemock之c++测试工程(CLion)

1. Gmock 简介

Gmock是google开发的一套辅助测试的工具,它往往和GTest结合在一起使用。主要用于模拟其他模块约定的接口进行自测。即该接口形式已经定义,但实现并未给出,我们用Gmock模拟其内部实现,即设定方法运行形式,来进行测试。其作用就类似白盒测试中的打桩的概念。

测试某功能需要调用硬件或者其他服务,太过于复杂,例如测试对某函数对数据库的操作时,不需要真正调用数据库或者为了测试而搭建数据库,gmock可以将数据库接口打桩,模拟数据库的返回。
A模块调用B模块,目前测试A模块,但是B模块还没有实现,可以用gmock去B模块打桩,完成A模块对B模块的调用和测试。

  1. 测试某功能需要调用硬件或者其他服务,太过于复杂,例如测试对某函数对数据库的操作时,不需要真正调用数据库或者为了测试而搭建数据库,gmock可以将数据库接口打桩,模拟数据库的返回。
  2. A模块调用B模块,目前测试A模块,但是B模块还没有实现,可以用gmock去B模块打桩,完成A模块对B模块的调用和测试。

2. 编译googletest,生成静态库

我们要搭建gtest 测试工程,其实只需要将自己的测试单元程序与googletest的静态库链接起来。

在googletest 根工程根目录创建build文件夹,并进入build文件夹,可以使用明令行完成

mkdir build
cd build

接下来开始编译

cmake .. -G "MinGW Makefiles"
// 如果此前执行过cmake没有编译出想要的库,需要先删除CMakeCache.txt再重新执行

 生成MakeFile之后,执行 make 命令

make
// 或者使用 cmake --build .

编译成功后,会在build文件夹下新生成一个lib文件夹,里面保存编译好的 libmock_main.a、libmock.a/ libgtest.a、libgtest_main.a。这四个静态库就是我们搭建自己的单元工程需要的。

3. 搭建单元测试工程

动手党可参考 windows从零搭建googletest之c++测试工程(CLion)

拿来党可下载 GitCode

4. Gmock 函数

三种mock模式

using ::testing::NiceMock;
using ::testing::NaggyMock;
using ::testing::StrictMock;
  1. NiceMock:NiceMock是一种宽松的Mock对象,它允许调用任何方法,而不会抛出异常。如果你不关心某些方法是否被调用,或者你只是想测试一些简单的场景,那么使用NiceMock是一个不错的选择。
  2. NaggyMock:NaggyMock是一种中等程度的Mock对象,它会在你没有设置期望的方法被调用时发出警告。这对于确保你的测试覆盖了所有需要测试的方法非常有用。
  3. StrictMock:StrictMock是一种严格的Mock对象,它会在你没有设置期望的方法被调用时抛出异常。这对于确保你的代码按照预期的方式运行非常有用,但是需要更多的设置和维护。

知道你也懒得看,那就用 NaggyMock 吧。

gMock典型应用流程:

  1. 引入用到的gMock名称
  2. 建立模拟对象
  3. 设置模拟对象默认动作
  4. 在模拟对象上设置预期

MOCK_METHOD

MOCK_METHOD(return_type, func_name, (args...), (specs));

 举个栗子:

对于函数:bool function(char * str1, char *str2) const override;

  对应测试方法声明为:

MOCK_METHOD(bool, function, (char *, char *), (const override));

MOCK_METHODx

实现需要新写一个类继承于基类,基类包括将要测试的函数,包括纯虚函数等。

在类内我们定义测试接口的方法:

MOCK_METHODx(func_name,return_type(args...) );

 x和函数的参数个数有关,func_name为函数名,return_type为函数func_name返回类型,args为参数表。

举个栗子:

对于函数:bool function(char * str1, char *str2);

 对应测试方法声明为:

MOCK_METHOD2(function,bool(char * str1, char *str2));

EXPECT_CALL

构建类和方法后,我们可以通过调用

 EXPECT_CALL(mock_object, function(matchers))

//       .With(...)

//       .Times(...)

//       .InSequence(...)

//       .After(...)

//       .WillOnce(...)

//       .WillRepeatedly(...)

//       .RetiresOnSaturation();

EXPECT_CALL 声明一个调用期待,function是mock_object对象中的mock方法,参数可通过matchers规则匹配。参数表的 _ 代表通配符,可以用任意参数代替进行控制。

_可替换为匹配器,单值匹配可以直接填入该值,详细的可调用自带匹配器,或手动编写。

方法释义
With指定多个参数的匹配方式
Times设定方法调用的次数
InSequence指定函数执行的顺序
After指定某个方法只能在另一个方法之后执行
WillOnce执行一次方法时,将执行其参数的方法。一般我们使用Return方法,用于指定一次调用的输出。
WillRepeatedly表示一直调用一个方法时,将执行其参数的方法。
RetiresOnSaturation保证期待调用不会被相同的函数的期待所覆盖。

 ON_CALL 和 EXPECT_CALL 区别

在 Google Mock 中,ON_CALL 和 EXPECT_CALL 都是用于设置模拟对象的行为的函数。 ON_CALL 用于设置一个模拟对象的预期行为,但不会检查该行为是否被调用。也就是说,如果设置了 ON_CALL,但是该行为没有被调用,测试也不会失败。

EXPECT_CALL 用于设置一个模拟对象的预期行为,并且会检查该行为是否被调用。如果设置了 EXPECT_CALL,但是该行为没有被调用,测试会失败。

因此,ON_CALL 适用于那些不是必须被调用的行为,而 EXPECT_CALL 适用于那些必须被调用的行为。

testing::Return

return方法,用于模拟被mock函数的返回值:

testing::Return(true)

testing::Return("123")

 匹配器(Matcher)

作用:对一个对象进行验证匹配器可用在ON_CALL()及EXPECT_CALL()的matcher位置上,也可单独使用。

EXPECT_THAT(value, matcher) 

ASSERT_THAT(value, matcher) 

类型关键字用法说明
通用匹配

1. _

2.A<type>()或者An<type>()

1. 任意类型的参数都可以匹配

2.任何type类型的参数都可以匹配

一般匹配

Ge(value)

Gt(value)

Le(value)

Lt(value)

Ne(value)

IsNull()、NotNull()

参数>=value

参数>value

参数<=vaule

参数<value

参数!=value

参数是空指针、参数是非空指针

浮点数匹配

DoubleEq(double_value)

FloatEq(float_value)

参数= double_value

参数= float_value

字符串匹配

EndsWith(suffix)

StartWith(prefix)

HasSubstr(string)

StrEq(string)

StrNe(string)

参数以后缀suffix结尾

参数以前缀prefix开始

参数包含string子字符

参数与string相同,大小写敏感

参数与string不同,大小写敏感

容器匹配

ContainerEq(container)

contains(element)

Each(element)

Sizels(m)

IsEmpty

参数和container有相同内容

包含满足e的元素,element为值

参数每个元素都满足element,element可以为值

参数的长度符合m的要求

参数为空容器

指针匹配

Pointee(m)

参数(指针)指向的内容符合m

行为(Action)

gmock可选择使用系统或者用户自定义的行为

类型关键字用法说明
默认行为DoDefault()调用系统或者用户使用ON_CALL定义的默认行为
返回值

Return()

Return(value)

ReturnNull()

ReturnPointee(ptr)

ReturnRef(variable)

没有返回值的返回,适用于void函数

返回一个value值,必要时会做类型转换

返回一个空指针

返回指针ptr指向的值

返回variable的引用

副行为

Assign(&variable, value)

Throw(exception)

将value赋给variable

抛出异常exception

组合行为IgnoreResult(a)调用a但是忽略它的结果,a必须有返回值

次数生成器 

次数生成器用于生成Times()中的次数参数

关键字用法说明
AnyNumber()任意次数
AtLeast()期望最少n次
AtMost()期望最多n次
Between(m,n)期望介于m次和n次之间,包含m和n
Exactly(n)期望n次

期望次序设置

 Mock期望存在时时序关系,可指定满足的次序,行为有时序的期望链条

类型说明
After指定期望被调用后才允许调用其他期望
InSequence对象InSequence对象的作用域范围内的期望必须已定义的顺序调用
Sequence对象通过调用InSequence定义在同一个Sequence对象上的所有期望,必须以与定义时相同的顺序被调用

gmock 的约束

  1. 只能mock类的虚函数
  2. 对静态函数支持不友好
  3. 在调用mock函数前需设置好预期,否则其行为未定义
  4. 不支持多线程测试

因为静态函数是在类的命名空间中定义的,而不是在类的作用域中定义的,所以 gmock 无法直接模拟静态函数。但是,可以通过将静态函数包装在一个类中,然后使用 gmock 模拟该类来模拟静态函数。另外,也可以使用依赖注入等技术来避免对静态函数的直接依赖,从而使测试更加灵活和可维护。

// 被测对象
class MyClass {
public:
    static int StaticFunction() {
        // 静态函数的实现
    }
};

// 模拟对象
class MockClass {
public:
    MOCK_METHOD(int, StaticFunction, (), (const));
};

// 测试用例
TEST(MyClassTest, StaticFunctionTest) {
    MockClass mock;
    EXPECT_CALL(mock, StaticFunction())
        .WillOnce(Return(42));  // 模拟静态函数的返回值为42

    MyClass myObj;
    int result = myObj.StaticFunction();  // 使用模拟函数替代静态函数

    EXPECT_EQ(result, 42);
}

4. Gmock 使用实例

GitCode

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在Linux上使用CLion进行C++功能测试是很常见的。CLion是一款功能强大的集成开发环境,专为C和C++开发而设计。它提供了许多有用的功能,如代码自动完成、调试器、版本控制集成等,可以帮助开发者更高效地编写和调试代码。在Linux上使用CLion进行C++功能测试时,可以使用友元函数来访问类的私有和保护成员。友元函数是一种特殊的函数,可以在类的任何地方声明,并且可以访问类的私有和保护成员。在C++中,友元函数的调用与普通函数的调用原理相同。在CLion中,可以使用重载的流插入运算符和流提取运算符来输出和输入C++标准类型的数据。这些运算符已经在类库提供的头文件中进行了重载,因此可以直接使用cout和cin来进行输入输出操作。为了使用这些运算符,需要在程序文件中包含iostream头文件。友元函数的定义可以在类的内部进行,这样可以隐含this指针,并且可以将cout和cin作为参数传递给重载的操作符函数。这样就可以在CLion中使用友元函数来进行C++功能测试了。 #### 引用[.reference_title] - *1* *2* *3* [日期类的实现(C++)](https://blog.csdn.net/weixin_57604904/article/details/127424931)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值