mock non-virtual methods
生产代码中有很多类方法是非虚的,而为了在Gtest中解除这些非必需的依赖,可以通过Gmock的mock non-virtual methods using templates方法来达到目的。
在此之前,需要了解一种设计模式:Dependency Injection,依赖注入。虽然这个概念始于Java和.net,但在面向对象编程中,C++代码同样应该遵循。
Ps:软件工程中的一个重要的理念就是关注分离(Separation of concern, SoC)。依赖注入不是目的,它是一系列工具和手段,最终的目的是帮助我们开发出松散耦合(loose coupled)、可维护、可测试的代码和程序。这条原则的做法是大家熟知的面向接口,或者说是面向抽象编程。
如何重构代码达到DI的目的呢,下面是一个例子。
原代码:
class A{
public:
int Funtion1(B& obj) {
//do something
std::string str = “mock non-virtual methods using templates”;
auto rst = obj.Function2(str);
//do something
}
}
class B{
public:
int Funtion2(std::string _str){ puts(_str.c_str()); }
}
当我们对类A的方法Function1进行UT防护的时候,不关心其中类B的方法Function2的执行结果,这时候该如何对其进行mock呢(Function2是非虚的)?
在以上这种代码结构中,答案是无法进行mock!除非把Function2修改为virtual或者使用下面的方法:
修改后:
emplate <class T1 >
class RefactorA{
public:
int Funtion1(T1 & obj) {
//do something
std::string str = “mock non-virtual methods using templates”;
auto rst = obj.Function2(str);
//do something
}
}
重构之后,类RefactorA变成了类模板,在实例化的时候把依赖的类B显式的“注入”进去,这时候进行UT的时候,就可以把“注入”的类B的方法Function2 进行mock,代码如下:
//对类B中的Function2进行mock
class mockB
{
public:
MOCK_METHOD1(Funtion2, int (std::string ));
};
/对类A进行UT测试
class RefactorA _UT : public :: testing::Test
{
protected:
virtual void SetUp(){}
virtual void TearDown(){} RefactorA < mockB > mockObjA;//实例化模板类
}; TEST_F(RefactorA _UT , Funtion1)
{
//期望类B的方法Function2被调用至少一次,返回值为100,参数为任意字符串
mockB mockObjB;
EXPECT_CALL(mockObjB, Funtion2 (_))
.Times(AtLeast())
.WillOnce(Return()); auto rst = mockObjA.Function1( mockObjB );//注意这里传入的是mock出来的对象 EXPECT_TRUE( rst );
}
把类B的方法Function2 mock之后,UT的重点就可以放在对Function1的其它分支上了。
重点:将类A改写为类模板之后,在生产代码中,需要使用真正的类B对象来进行模板类的实例化,而在测试代码中,则需要使用mock出来的类B对象进行模板类的实例化。它们之间的无关的,这与mock接口类的虚函数有着本质的区别。
附:
类模板方法的声明和定义有以下4种方法,可以酌情使用:
① 荐做法是方法在定义的时候就进行实现(类RefactorA);
② 再者是,声明在模板类中,实现在模板类外,但要在一个文件中;
③ 把方法的实现写入xxx.inl文件,然后在模板类的结尾使用#include “xxx.inl”;
④ 把方法的实现写入xxx.cpp文件,但在cpp文件的最开始需要将模板类实例化。
总之,为了写出可UT的代码,需要时刻牢记“依赖注入”这个原则。
欢迎讨论。
mock non-virtual methods的更多相关文章
- What’s wrong with virtual methods called through an interface
May 31, 2016 Calling a virtual method through an interface always was a lot slower than calling a st ...
- why do we need virtual methods in C++?
http://stackoverflow.com/questions/2391679/why-do-we-need-virtual-methods-in-c Basic idea: when mark ...
- 【转载】#349 - The Difference Between Virtual and Non-Virtual Methods
In C#, virtual methods support polymorphism, by using a combination of the virtual and override keyw ...
- Rhino Mock
mock interfaces, delegates and classes, including those with parameterized constructors. set expecta ...
- [转载] google mock cookbook
原文: https://code.google.com/p/googlemock/wiki/CookBook Creating Mock Classes Mocking Private or Prot ...
- CLR via C# 3rd - 08 - Methods
Kinds of methods Constructors Type constructors Overload operators Type con ...
- 8.Methods(一)
1.Instance Constructors and Classes (Reference Types) Constructors methods : 1.allow an instance of ...
- (转) Virtual function
原文地址:http://en.wikipedia.org/wiki/Virtual_function In object-oriented programming, a virtual functio ...
- Should I expose asynchronous wrappers for synchronous methods?
Lately I've received several questions along the lines of the following, which I typically summarize ...
- why pure virtual function has definition 为什么可以在基类中实现纯虚函数
看了会音频,无意搜到一个frameworks/base/include/utils/Flattenable.h : virtual ~Flattenable() = 0; 所以查了下“纯虚函数定义实现 ...
随机推荐
- C# 生成Model和DAL
using Model; using System.Collections.Generic; using System.Text; public class Class1 { #region 生成Mo ...
- 网站顶部显示预加载进度条preload.js
网站加载的速度快的话,不会显示进度条加载时候的样式. 支持性主流浏览器都支持,ie浏览器需要9以上9也支持. 使用方法 <script src="http://code.jquery. ...
- day01_20181223
今日内容大纲:1,python的出生于应用.2,Python的历史. python2x: 源码冗余,源码重复,源码不规范. python3x:源码清晰优美简单. ...
- 服务器安装ESXI6.5系统
服务器做raid5磁盘冗余配置步骤 1.打开服务器电源,进入服务器启动界面,按下F10后回车,等待服务器回应你的操作进入下一个页面 提示: 在进入服务启动页面,在页面的最下方就可以看到F9,F10, ...
- Python笔记9-----不等长列表转化成DataFrame
1.不同长度的列表合并成DataFrame. 法1: ntest=['a','b'] ltest=[[1,2],[4,5,6]] 先变成等长的列表:(a:1),(a:2),(b:4),(b:5),(b ...
- nyoj181-小明的难题
小明的难题时间限制:3000 ms | 内存限制:65535 KB难度:2描述课堂上小明学会了用计算机求出N的阶乘,回到家后就对妹妹炫耀起来.为了不让哥哥太自满,妹妹给小明出了个问题"既 ...
- [luogu3952 noip2017] 逛公园 (计数dp+最短路)
传送门 Description Input Output 输出文件包含 T 行,每行一个整数代表答案. Sample Input 2 5 7 2 10 1 2 1 2 4 0 4 5 2 2 3 2 ...
- JZOJ5804. 【2018.08.12提高A组模拟】简单的序列
性质:每个位置的前缀和必须大于0,总和=0.以此dp即可. #include <iostream> #include <cstdio> #include <cstring ...
- java+selenium+testNG+excel 实现 web 网页的自动化测试
webdriver的关键字从excel读取,这样测试人员只需要在excel中填写相关用例即可 前端微站和后台系统的用例可整合在同一excel中,这样可实现前端与后台的闭循环测试 除了一些基本的校验规则 ...
- js里写html代码 啥时候要用“\"转义
当去掉\的时候 字体变黑 需要加\