在进行测试过程中,待测的类或者方法经常会依赖其他类或方法的实现。如果此时这些依赖还没有实现,则需要打桩。另外测试讲求独立,测试之间的互相依赖会导致测试最终混乱不堪。

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)的更多相关文章

  1. Arcade初探[0] 目录与导航

    2017年6月,ESRI开发者页面出现了一个新玩意儿:Arcade. 连接:点我 这是什么东西呢?有什么用呢? 1. 是什么 Arcade一种表达语言,可以在ArcGIS平台上使用.不管是编写简单的脚 ...

  2. GoogleTest初探(0)

    单元测试是一种保证代码质量的手段.程序员可以通过写单元测试来保证自己写的代码的功能正确. 本人所在公司使用GoogleTest测试框架来进行单元测试.虽然现在在公司的工程代码中写单元测试已经驾轻就熟, ...

  3. Spring入门(9)-AOP初探

    Spring入门(9)-AOP初探 0. 目录 什么是面向切面编程 AOP常见术语 AOP实例 参考资料 1. 什么是面向切面编程 Aspect Oriented Programming(AOP),即 ...

  4. ZAM 3D 制作简单的3D字幕 流程(二)

    原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...

  5. ZAM 3D 制作3D动画字幕 用于Xaml导出

    原地址-> http://www.cnblogs.com/yk250/p/5662788.html 介绍:对经常使用Blend做动画的人来说,ZAM 3D 也很好上手,专业制作3D素材的XAML ...

  6. 微信小程序省市区选择器对接数据库

    前言,小程序本身是带有地区选着器的(网站:https://mp.weixin.qq.com/debug/wxadoc/dev/component/picker.html),由于自己开发的程序的数据是很 ...

  7. osg编译日志

    1>------ 已启动全部重新生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake do ...

  8. Android BLE与终端通信(五)——Google API BLE4.0低功耗蓝牙文档解读之案例初探

    Android BLE与终端通信(五)--Google API BLE4.0低功耗蓝牙文档解读之案例初探 算下来很久没有写BLE的博文了,上家的技术都快忘记了,所以赶紧读了一遍Google的API顺便 ...

  9. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探

    更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjoy8/BlogArti ...

随机推荐

  1. 修改maven默认的jdk版本

    修改maven默认的jdk版本,想改彻底需要在maven的全局配文件(settings.xml)增加以下信息:   在profiles 节点下增加: <profile> <id> ...

  2. Taro 是一套遵

    https://github.com/NervJS/taro 使用 Taro,我们可以只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信小程序.H5.React-Nat ...

  3. select 时进行update的操作,在高并发下引起死锁

    场景:当用户查看帖子详情时,把帖子的阅读量:ReadCount+1 select title,content,readcount from post where id='xxxx'   --根据主键查 ...

  4. leetcode Ch3-DFS & Backtracking I

    一.树的遍历 [非递归版] 1. 后序 class Solution { public: vector<int> postorderTraversal(TreeNode *root) { ...

  5. RCLighting

    RCLighting https://github.com/RidgeCorn/RCLighting 效果: 真机测试的效率: 看了源码,其实原理很简单: ====================== ...

  6. Linux入门-7 Linux管道、重定向以及文本处理

    Linux管道.重定向以及文本处理 1 Linux多命令协作:管道及重定向 管道和重定向 2 Linux命令行文本处理工具 文件浏览 基于关键字搜索-grep 基于列处理文本-cut 文本统计-wc ...

  7. 一点二次插值、二点二次插值 ,matlab

    syms f x a b c; f(x)=3*x^4-4*x^3-12*x^2; q(x)=a*x^2+b*x+c; %二点二次插值 x=[-1.2 -0.8]; ff=diff(diff(f)); ...

  8. apt安装mysql

    使用 APT 安装 MySQL 参考官方文档 apt-get install mysql-server 这将安装MySQL服务器的包,以及客户端和数据库公共文件的包. 在安装过程中,系统会要求您为ro ...

  9. CSS3动画中的位置设定问题

    水平居中的不同方法实现: position: absolute; margin: auto; left:; right:; position: absolute; left:%; -webkit-tr ...

  10. Mac Sublime Text3快捷键

    下载地址http://www.sublimetext.com/3 一.安装Package Control 按Ctrl + ` 调出console,粘贴下列安装代码到底部命令行并回车: import u ...