白盒测试之gmock入门篇
一、gmock是什么
gmock是google公司推出的一款开源的白盒测试工具。gmock是个很强大的东西,测试一个模块的时候,可能涉及到和其他模块交互,可以将模块之间的接口mock起来,模拟交互过程。其作用就类似白盒测试中的打桩的概念。
下面简单的说说打桩在白盒测试中的重要性:
1、比如银行业务,需要测试业务模块。此时,不可能去操作真实的数据库,并且搭建新的数据库可能比较复杂或者耗时。那么就可以用gmock将数据库接口地方打桩,来模拟数据库操作。
2、比如要测试A模块,必过A模块需要调用B模块的函数。如果B模块还没有实现,此时,就可以用gmock将B模块的某些接口打桩。这样就可以让A模块的测试继续进行下去。
3、比如网关设备,在用gtest测试device模块的时候,必须有真实的设备才能让测试进行下去。如果用gmock模拟一套sdk接口,那么无需真实的设备也能让测试进行下去。(本条仅限公司内部阅读)
二、gmock如何获取
gmock是google的开源工具,google的官网上是可以下载源码的。不过公司内部员工可以去0.2上去取,在“研发质量部”的文件夹下。gmock的最新版本是1.7.0。下载下来的压缩包名称为“gmock-1.7.0.zip”。解压后,如下:

仔细观察发现,压缩包里面有gtest的文件夹,该文件夹里面就是gtest的源码。因为大部分情况下,gmock是配合gtest来做白盒测试的。关于gtest的工程相关介绍请查看本博客其他文章。
本文暂时讨论windows下的gmock编译,工程相关的文件在msvc的文件夹中。msvc文件夹下又分为2005和2010文件夹,分别是用VS2005和VS2010建立的工程。
用VS2010打开工程,然后直接编译。编译通过后,会得到gmock.lib,gmock_maim.lib,gmock_test.ext三个文件。其中gmock.lib就是我们所需要的库文件,其他两个工程本文暂不做阐述。
三、gmock的第一个demo
我们暂且模拟银行转账系统。银行转账系统涉及到数据库两个操作,首先要通过银行卡ID找到账户信息(包括账户余额等),然后在通过计算,将转账后的金额写入到转账双方。这样就完成了简单的银行转账业务。
下面我们来mock(模拟)数据库的查询账户和写入金额的两个方法,定义一个头文件AccountManager.h :
// AccountManager.h
// the interface of external services which should be mocked
// 需要被mock的服务接口
#pragma once #include <string> #include "Account.h" class AccountManager
{
public:
//通过账户号,找到对应的用户
virtual Account findAccountForUser(const std::string& userId) = ;
//更新用户的信息这里
virtual void updateAccount(const Account& account) = ;
};
AccountManager是需要被mock(模拟)的类。其中findAccountForUser(找到对应用户)和updateAccount(更新账户信息)是本次转账要mock的两个方法。注意,此处的两个方法用的是纯虚函数。因为这两个方法无需实现,测试的时候程序会走到mock出来的函数中,即使实现, 也不会被调用到。
下面通过gmock来mock(模拟)AccountManager的两个方法:
// MockAccountManager, mock AccountManager with googlemock
class MockAccountManager : public AccountManager
{
public:
MOCK_METHOD1(findAccountForUser, Account(const std::string&)); MOCK_METHOD1(updateAccount, void(const Account&));
};
类MockAccountManager是继承数据库DB方法类AccountManager的。其中MOCK_METHOD1为gmock的宏定义。头文件中还有其他类似宏定义,如MOCK_METHOD0,MOCK_METHOD2...
MOCK_METHOD#1(#2, #3(#4) )
#2是你要mock的方法名称!#1表示你要mock的方法共有几个参数,#4是这个方法具体的参数,#3表示这个方法的返回值类型。很简单不是?!
// Account.h
// basic application data class
#pragma once #include <string> class Account
{
private:
std::string accountId; //账号 long balance; //存款 呃 还是叫余额吧 public:
Account(); Account(const std::string& accountId, long initialBalance); //消费
void debit(long amount); //收入
void credit(long amount); //获取存款
long getBalance() const; //获取账号
std::string getAccountId() const;
};
上面这个类是为了方便模拟转账业务构造的一个账户类。类Account有debit(消费)、credit(收入)、getBalance(获取存款)和getAccountId(获取账号)四个方法。
// A facility class acts as an external DB
class AccountHelper
{
private:
std::map<std::string, Account> mAccount;
// an internal map to store all Accounts for test public:
AccountHelper(std::map<std::string, Account>& mAccount); void updateAccount(const Account& account); Account findAccountForUser(const std::string& userId);
}; AccountHelper::AccountHelper(std::map<std::string, Account>& mAccount)
{
this->mAccount = mAccount;
} void AccountHelper::updateAccount(const Account& account)
{
this->mAccount[account.getAccountId()] = account;
} Account AccountHelper::findAccountForUser(const std::string& userId)
{
if (this->mAccount.find(userId) != this->mAccount.end())
return this->mAccount[userId];
else
return Account();
}
上面这个类,扮演着数据库的就角色。mock(模拟)出来的方法,都将用该类的函数替代实现。
下面,我们来写一个测试用例来看看gmock的神奇作用。
// Test case to test AccountService
TEST(AccountServiceTest, transferTest)
{
std::map<std::string, Account> mAccount;
mAccount["A"] = Account("A", );
mAccount["B"] = Account("B", );
AccountHelper helper(mAccount); MockAccountManager* pManager = new MockAccountManager(); // specify the behavior of MockAccountManager
// always invoke AccountHelper::findAccountForUser
// when AccountManager::findAccountForUser is invoked
EXPECT_CALL(*pManager, findAccountForUser(testing::_)).WillRepeatedly(
testing::Invoke(&helper, &AccountHelper::findAccountForUser)); // always invoke AccountHelper::updateAccount
//when AccountManager::updateAccount is invoked
EXPECT_CALL(*pManager, updateAccount(testing::_)).WillRepeatedly(
testing::Invoke(&helper, &AccountHelper::updateAccount)); AccountService as;
// inject the MockAccountManager object into AccountService
as.setAccountManager(pManager); // operate AccountService
as.transfer("A", "B", ); // check the balance of Account("A") and Account("B") to
//verify that AccountService has done the right job
EXPECT_EQ(, helper.findAccountForUser("A").getBalance());
EXPECT_EQ(, helper.findAccountForUser("B").getBalance()); delete pManager;
}
首先,声明一个类MockAccountManager的实例pManager,在声明一个实现类AccountHelper实例helper。EXPECT_CALL的作用是将调用pManager方法替换成实现类helper的对应方法。此处,将pManager的findAccountForUser方法替换成helper的findAccount方法,将pManager的updateAccount方法替换成helper的updateAccount方法。
最后,再用gtest的断言机制EXPECT_EQ来判断结果。
白盒测试之gmock入门篇的更多相关文章
- 白盒测试之JUnit与SpringTest的完美结合
通过白盒的单元测试可以验证程序基本功能的有效性,从而保证整个系统的质量,功在一时,利在千秋.目前80%以上公司后台还是基于java,尤其是后台大量采用Spring框架,我们这里采用Junit和Spri ...
- 白盒测试之gtest第一个demo
认识gtest工具后,关于它的使用,下面将用一个demo程序演示一下gtest的用法以及成果展示. 一.需要测试的C++代码: #include "myfunction.h" // ...
- 1. web前端开发分享-css,js入门篇
关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人与人的教育背景与成长环境心理活动都有差别,但就别人的心得再结合自己的特点,然后探索适合自己的学 ...
- 浅析白盒审计中的字符编码及SQL注入
尽管现在呼吁所有的程序都使用unicode编码,所有的网站都使用utf-8编码,来一个统一的国际规范.但仍然有很多,包括国内及国外(特别是非英语国家)的一些cms,仍然使用着自己国家的一套编码,比如g ...
- web前端开发分享-css,js入门篇(转)
转自:http://www.cnblogs.com/jikey/p/3600308.html 关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人 ...
- Tesseract——OCR图像识别 入门篇
Tesseract——OCR图像识别 入门篇 最近给了我一个任务,让我研究图像识别,从我们项目的screenshot中识别文字信息,so我开始了学习,与大家分享下. 我看到目前OCR技术有很多,最主要 ...
- 腾讯QQ会员技术团队:人人都可以做深度学习应用:入门篇(下)
四.经典入门demo:识别手写数字(MNIST) 常规的编程入门有"Hello world"程序,而深度学习的入门程序则是MNIST,一个识别28*28像素的图片中的手写数字的程序 ...
- Hadoop生态圈-大数据生态体系快速入门篇
Hadoop生态圈-大数据生态体系快速入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.大数据概念 1>.什么是大数据 大数据(big data):是指无法在一定时间 ...
- web前端开发分享-css,js入门篇
学习没有捷径,但学习是有技巧与方法. 一,css入门篇: 推荐书籍:css哪些事儿,精通css. 理由:css那些事儿,他是一本介绍css基础类的书,是入门的经典读物. 系统的介绍了css的选 ...
随机推荐
- SQL server 复习一
第一天 下面我们从最基础的开始: 在运行里面输入:services.msc 一.启动服务 二.数据库登录的两种身份验证方式 另外一种身份验证方式就是SQL Server身份验证. sa不能使用的时候可 ...
- 关于C#中timer类
·关于C#中timer类 在C#里关于定时器类就有3个 1.定义在System.Windows.Forms里 2.定义在System.Threading.Timer类里 3.定义在System.Tim ...
- Spring 3.0: Unable to locate Spring NamespaceHandler for XML schema namespace
被这个问题折磨着很久:参考: http://have23.iteye.com/blog/1340777 (cfx 与 spring 整合的时候出现的问题: org.springframework.be ...
- lintcode 中等题:kth-largest-element 第k大元素
题目 第k大元素 在数组中找到第k大的元素 样例 给出数组[9,3,2,4,8],第三大的元素是4 给出数组 [1,2,3,4,5],第一大的元素是5,第二大的元素是4,第三大的元素是3,以此类推 注 ...
- C语言中时间调用处理的相关函数介绍
asctime(将时间和日期以字符串格式表示) 相关函数:time,ctime,gmtime,localtime 表头文件:#include<time.h> 定义函数:char * asc ...
- Android:文件夹显示红色叹号
有感叹号,说明有的文件损坏或丢失了 解决方法: 右击工程,Build Path..->Configure Build Path...->Java Build Path 可以看到引用的jar ...
- PHP中该怎样防止SQL注入?
因为用户的输入可能是这样的: ? 1 value'); DROP TABLE table;-- 那么SQL查询将变成如下: ? 1 INSERT INTO `table` (`column`) VAL ...
- Zookeeper集群和HBase集群
1.部署Zookeeper集群(hadoop0\hadoop1\hadoop2) 1.1.在hadoop0上解压缩Zookeeper-3.4.5.tar.gz 1.2.执行命令 cp conf/zoo ...
- Hadoop1.x与Hadoop2的区别
转自:http://blog.csdn.net/fenglibing/article/details/32916445 六.Hadoop1.x与Hadoop2的区别 1.变更介绍 Hadoop2相比较 ...
- java 语言里 遍历 collection 的方式
我来简单说一下吧,一般有2种方法来遍历collection中的元素,以HashSet为例子HashSet hs=new HashSet();hs.add("hello");hs.a ...