GoogleMock初探(0)
在进行测试过程中,待测的类或者方法经常会依赖其他类或方法的实现。如果此时这些依赖还没有实现,则需要打桩。另外测试讲求独立,测试之间的互相依赖会导致测试最终混乱不堪。
GoogleMock提供一套方法来快速的实现打桩,并让打桩的类或者方法轻松的按照你的要求来进行一系列动作。
现在有一个还没实现具体方法的的抽象基类
//MyClass.hpp
#pragma once class MyClass
{
public:virtual int add(int a, int b) = ; virtual int plus(int a, int b) = ;
};
一个要使用其方法的类
//UseMyClass.hpp
#pragma once #include "MyClass.hpp" class UseMyClass
{
public:
int useAddAndPlus(int a, int b)
{
return myclass->add(a, b) + myclass->plus(a, b);
} void set(MyClass* m)
{
myclass = m;
}
private:
MyClass* myclass;
};
现在要对UseMyClass进行单元测试,但它的方法又依赖于MyClass中方法的实现,这种情况下就要对MyClass进行mock
//MockMyClass.hpp
#pragma once #include <gmock/gmock.h>
#include "MyClass.hpp" class MockMyClass : public MyClass
{
public:
MOCK_METHOD2(add, int(int a, int b));
MOCK_METHOD2(plus, int(int a, int b));
};
最后在测试的时候调用mock的方法,并设置其预期的动作
//MockTest.cpp
#include <gtest/gtest.h>
#include "UseMyClass.hpp"
#include "MockMyClass.hpp" TEST(TestUseMyClass, useAddAndPlus)
{
UseMyClass useMyClass;
MockMyClass mockMyClass;
EXPECT_CALL(mockMyClass, add(,)).WillOnce(testing::Return());
EXPECT_CALL(mockMyClass, plus(,)).WillOnce(testing::Return());
useMyClass.set(&mockMyClass);
EXPECT_EQ(, useMyClass.useAddAndPlus(, ));
}
编译
g++ mockTest.cpp -lgtest -lgtest_main -lgmock -lpthread -o myMock
运行结果

以上就是一个简单的使用GoogleMock的例子。下面介绍一下如何写mock的代码:
1. 必须包含头文件<gmock/hmock.h>
2. 对于一个待mock的方法
ReturnType func(arg0, arg1,....)
其mock方法的书写方式为:
MOCK_METHODn(func, ReturnType(arg0, arg1, ...))
其中n为参数个数
3. 对于在测试中mock方法的期待动作的基础写法:
EXPECT_CALL(mock_object, method(matchers))
.Times(cardinality)
.WillOnce(action)
.WillRepeatedly(action);
EXPECT_CALL声明一个调用期待,就是我们期待这个对象的这个方法按什么样的逻辑去执行。
mock_object是mock的对象,例如上例中的mockMyClass
method是mock的方法,例如上例中的add, plus
Times表示这个方法期望被执行多少次
WillOnce表示执行一次方法时,将执行其参数action的方法。一般我们使用Return方法,用于指定一次调用的输出
WillRepeatedly表示一直调用方法时,将执行其参数action的方法。需要注意下它和WillOnce的区别,WillOnce是一次,WillRepeatedly是一直
举个例子:
EXPECT_CALL(mockMyClass, add(_,_))
.Times()
.WillOnce(Return())
.WillRepeatedly(Return())
这个例子表示,我们期望MyClass类的一个实例的方法add被调用6次,被调用是传入的参数不指定,但第一次被调用返回6,后面每次被调用返回3
例外注意,Times(cardinality) WillOnce(action) WillRepeatedly(action) 都不是必须要写的,按你自己的需要去选择要写哪个或者哪些
在公司的测试代码中像上例这种情况很少见,公司代码中mock不是为了为那些没有实现的方法打桩,而是为了减少UT之间的相互依赖。
试想如果class A 依赖于class B的实现,如果不给B打桩的话,A的UT肯定会依赖于B的实现,而有了mock则可以直接对依赖B的方法直接打桩而不去管B的真正实现,减少了测试的耦合性,使得测试间互相独立,容易调试。
下面对这种减少依赖而使用mock的情况举个例子:
一个实现其自己的方法的MyClass
//MyClass.hpp
#pragma once #ifdef UT
#include "MockMyClass.hpp"
class MyClass_orig
#else
class MyClass
#endif
{
public:
int add(int a, int b)
{
return a + b;
} int plus(int a, int b)
{
return a * b;
}
};
一个类的方法依赖于其他类(MyClass)方法的类UseMyClass
//UseMyClass.hpp
#pragma once #include "MyClass.hpp" class UseMyClass
{
public:
int useAddAndPlus(int a, int b)
{
return myclass->add(a, b) + myclass->plus(a, b);
} void set(MyClass* m)
{
myclass = m;
}
private:
MyClass* myclass;
};
对MyClass进行mock
//MockMyClass.hpp
#pragma once #include <gmock/gmock.h> class MyClass
{
public:
MOCK_METHOD2(add, int(int a, int b));
MOCK_METHOD2(plus, int(int a, int b));
};
最后对UseMyClass 进行测试
#define UT #include <gtest/gtest.h>
#include "UseMyClass.hpp" TEST(TestUseMyClass, useAddAndPlus)
{
UseMyClass useMyClass;
MyClass mockMyClass;
EXPECT_CALL(mockMyClass, add(,)).WillOnce(testing::Return());
EXPECT_CALL(mockMyClass, plus(,)).WillOnce(testing::Return(2));
useMyClass.set(&mockMyClass);
EXPECT_EQ(, useMyClass.useAddAndPlus(, ));
}
编译
g++ mockTest.cpp -lgtest -lgtest_main -lgmock -lpthread -o myMock
运行结果

注意,我故意让plus返回2,这样可以看出最后测试的时候用的是mock的类方法而非真正的类方法。
参考文章:
https://github.com/google/googletest/blob/master/googlemock/docs/ForDummies.md
GoogleMock初探(0)的更多相关文章
- Arcade初探[0] 目录与导航
2017年6月,ESRI开发者页面出现了一个新玩意儿:Arcade. 连接:点我 这是什么东西呢?有什么用呢? 1. 是什么 Arcade一种表达语言,可以在ArcGIS平台上使用.不管是编写简单的脚 ...
- GoogleTest初探(0)
单元测试是一种保证代码质量的手段.程序员可以通过写单元测试来保证自己写的代码的功能正确. 本人所在公司使用GoogleTest测试框架来进行单元测试.虽然现在在公司的工程代码中写单元测试已经驾轻就熟, ...
- Spring入门(9)-AOP初探
Spring入门(9)-AOP初探 0. 目录 什么是面向切面编程 AOP常见术语 AOP实例 参考资料 1. 什么是面向切面编程 Aspect Oriented Programming(AOP),即 ...
- ZAM 3D 制作简单的3D字幕 流程(二)
原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...
- ZAM 3D 制作3D动画字幕 用于Xaml导出
原地址-> http://www.cnblogs.com/yk250/p/5662788.html 介绍:对经常使用Blend做动画的人来说,ZAM 3D 也很好上手,专业制作3D素材的XAML ...
- 微信小程序省市区选择器对接数据库
前言,小程序本身是带有地区选着器的(网站:https://mp.weixin.qq.com/debug/wxadoc/dev/component/picker.html),由于自己开发的程序的数据是很 ...
- osg编译日志
1>------ 已启动全部重新生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake do ...
- Android BLE与终端通信(五)——Google API BLE4.0低功耗蓝牙文档解读之案例初探
Android BLE与终端通信(五)--Google API BLE4.0低功耗蓝牙文档解读之案例初探 算下来很久没有写BLE的博文了,上家的技术都快忘记了,所以赶紧读了一遍Google的API顺便 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探
更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjoy8/BlogArti ...
随机推荐
- WiFiDog 与 AuthServer
背景 在一些公共场所(比如公交车.地跌.机场等)连接当地的 WiFi 时会弹出一个验证表单,输入验证信息(比如短信验证码)后就能够通过该 WiFi 联网. 本文将介绍通过 OpenWrt WiFiDo ...
- Android 虚拟多开系列一——技术调研
参考链接:http://weishu.me Github源码链接: 国内Xposed框架源码链接 VirtualAp ...
- CentOS 7 Apache 多端口部署 Web Apps 指南
转载自简书,原作者xuyan0,链接https://www.jianshu.com/p/b34c78bf9bf0,如有侵权,请联系删除 导语 Apache web 服务器运行着互联网上超过半数的活跃的 ...
- Spring MVC基本配置和实现(三)
Item public class Item { private Integer id; private String name; public Integer getId() { return id ...
- js时间戳转换日期
//js时间戳转换日期function formatDate(now) { var year=now.getFullYear(); var month=now.getMonth()+1; var da ...
- LED相关
P10 模组 分辨率32*16 尺寸320*160 间距 10mm P8 模组 分辨率32*16 尺寸256*128 间距 8mm P7.62 模组 分辨率 ...
- ‘ActiveX component can’t create object解决方法
Event Type: WarningEvent Source: Health Service ScriptEvent Category: NoneEvent ID: 1Dat ...
- hbase shell基础和常用命令详解
HBase是Google Bigtable的开源实现,它利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为协同服 ...
- Office 365实现单点登录系列(1)—域环境搭建
Hello 小伙伴们, 2018新年快乐,作为2018年首篇文章,怎么能不给大家带来点干货呢?这篇文章其实我9月底的时候已经在MSDN上发布过了,为表诚意,我更新了这篇文章,并把它组成了一个系列,2. ...
- VS 2012 在 windows 8 中无法使用 Deubgger.Lunch() 对服务进行调试
找到了外文资料: Debugger.Launch() not displaying JIT debugger selection popup on Windows 8/8.1 If execu ...