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 ...
随机推荐
- c# copy类中值到另外一个对象中
贴图: 调用:
- Ubuntu 批量修改图片大小
现在的相机拍摄出来的照片通常远远大于电脑屏幕,不但尺寸很大,占用磁盘量也很大,我都是拍完照片立马就将其缩小到差不多HD的分辨率 改图片分辨率的软件有很多,除了耳熟能详的PS,Ubuntu下也有开源gi ...
- SVN的正确提交方式
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Rundy_Deng/article/details/80338093 也会让我们百思不得其解,甚至耽 ...
- winform基础控件总结
转自:http://www.cnblogs.com/top5/archive/2010/04/29/1724039.html 基础 - 常用控件 C# WinForm开发系列 - CheckBox/B ...
- DAO,SERVICE
- 执行系统命令,subprocess使用说明
os.system('ls -l') #只执行命令,不能将结果赋予变量 os.system('mkdir test') #创建test目录 files = os.popen('ls -l').rea ...
- Java学习---Collection的学习
Collection基本方法的使用 package com.huawei.ftl; import java.io.File; import java.io.FileInputStream; impor ...
- [BZOJ 4555][Tjoi2016&Heoi2016]求和
题意 给定 $n$ , 求下式的值: $$ f(n)= \sum_{i=0}^n\sum_{j=0}^i\begin{Bmatrix}i\\ j\end{Bmatrix}\times 2^j\time ...
- 使用android studio检测app内存泄漏【转载】
Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的crash,甚至可能出现因内存不足而导致APP崩溃. 一般检测android ...
- 配置Ceph集群为OpenStack后端存储
配置Ceph存储为OpenStack的后端存储 1 前期配置 Ceph官网提供的配置Ceph块存储为OpenStack后端存储的文档说明链接地址:http://docs.ceph.com/docs/ ...