嘲笑整个图书馆
Mocking an entire library
我正在开发使用boost::asio
的代码。为了测试它,我需要模拟这个库中的一组类。我正在使用Google Mock,它允许模拟虚拟方法。通常(和乏味)的过程是为我需要使用的每个类编写一个接口。
另一方面,Google Mock Cookbook描述了一种模拟非虚拟方法的替代方案:使用模板。就我而言,问题是我可能需要同时模拟多个类(因此直接使用模板不起作用)。所以我想:为什么不使用两级模板呢?我想出了以下解决方案:
// Classes to be mocked.
class RealA
{
public:
void a() { cout << "RealA::a()" << endl; };
};
class RealB
{
public:
void b() { cout << "RealB::b()" << endl; };
};
// Mock classes.
class MockA
{
public:
void a() { cout << "MockA::a()" << endl; };
};
class MockB
{
public:
void b() { cout << "MockB::b()" << endl; };
};
template<class ABFactory>
class Program
{
public:
void setFactory(ABFactory* factory) { factory = factory; }
void useA() { typename ABFactory::A* a = factory->createA(); a->a(); delete a; }
void useB() { typename ABFactory::B b; b.b(); }
private:
ABFactory* factory;
};
template<class ParamA, class ParamB>
class TABFactory
{
public:
typedef ParamA A;
typedef ParamB B;
A* createA() { return new A; };
B* createB() { return new B; };
};
typedef TABFactory<RealA, RealB> RealABFactory;
typedef TABFactory<MockA, MockB> MockABFactory;
然后,正常用法是:
Program<RealABFactory> p;
p.useA();
p.useB();
虽然测试将是:
Program<MockABFactory> t;
t.useA();
t.useB();
当模拟类具有具有复杂参数的方法(例如来自同一库的其他类可能不会被模拟)时,这开始变得复杂。总之,它似乎没有规模。对此解决方案有任何想法,或对解决问题的其他方法的建议?
Python Cog的完美用例
另请参阅此答案。
我已经使用 cog 为事件列表生成处理程序,处理程序代码非常通用,我不需要做特殊情况,但我仍然必须编写所有函数,所以我所做的是将事件保存在 .py 文件中的列表中,并在 python 函数中生成处理程序的样板代码。 所以我能够忠实于干燥原则
显然,您必须将COG添加到makefile的预构建中,以便使用工具链
。编辑 作为将样板添加到类所需的代码生成设计示例,我会做如下操作:
myCodeGeneration.py
import cog
ClassesToMock = [ [ 'IfaceA' , 'classA' , 'mockA' , ['void doSomething(int foo)' , 'int getSomething()']
, [ 'IfaceB', 'classB' , 'mockB' , ['static classA& getInstance()'] ]
def addInterfaces( myStructure ):
for classItem in myStructure:
cog.outl('class %s { ' % classItem[0] )
for methodDecl in classItem[3]:
cog.outl(' virtual %s = 0;' %methodDecl )
cog.outl(' } ')
#implement your real classes normally
def addMocks( myStructure ):
for classItem in myStructure:
cog.outl('class %s : public %s { ' % classItem[2] % classItem[0] )
for methodDecl in classItem[3]:
cog.outl(' %s {' %methodDecl )
cog.outl(' MOCK_STUFF_MACRO ')
cog.outl(' } ')
cog.outl(' } ')
然后在标题中:
伊法斯·
/*[[[cog
import cog
import myCodeGeneration
myCodeGeneration.addInterfaces( [ [ 'IfaceA' , 'classA' , 'mockA' , ['void doSomething(int foo)' , 'int getSomething()'] ] )
]]]*/
//your code will be generated here
//[[[end]]]
嘲笑A.h
/*[[[cog
import cog
import myCodeGeneration
myCodeGeneration.addMocks( [ [ 'IfaceA' , 'classA' , 'mockA' , ['void doSomething(int foo)' , 'int getSomething()'] ] )
]]]*/
//your code will be generated here
//[[[end]]]
此外,如果考虑将python添加到c ++源代码中,那么问题主要是"污染"它或"美化"它,这在很大程度上是品味和风格的问题。我认为 cog 为模板样式元编程提供了 c++ 中缺乏的补充,为程序员提供了提供代码整洁性和可读性的工具。但我不指望每个人都同意
对我来说,这种方法背后的整个架构设计原则是不要重复自己。 当我们必须在多个地方手动对方法进行编码时,就会发生错误。让计算机自动化其自动化功能,并对不能只编码一次的事情进行编码。作为副作用,它将使您的编码更加愉快,无论是编写还是以后阅读。
希望这有帮助
- 个人图书馆,数字正数或负数
- 像 POCO 这样的C++图书馆如何访问网络?
- 与第三方公共图书馆/代码接口
- Abseil和CMake在图书馆
- 如何制作跨平台图书馆
- MinGW在Cygwin上.关于链接GNU科学图书馆的一些问题
- 与libc相比,Gnu科学图书馆的性能较差
- 图书馆时间.H与C++
- C++的"皮条客我的图书馆"
- 制作不认识我的图书馆
- 谷歌丁克图书馆大楼C++
- 将Thirt-Party共享图书馆与Python Ctypes集成
- Visual Studio 2012静态图书馆与Visual Studio 2017
- Visual Studio 2017无法通过图书馆构建
- 如何获取当前图书馆路径
- 分配但不使用分配器的标准图书馆设施
- 带有Visual Studio的第三方图书馆
- Jacobi SVD的Eigen图书馆
- 在编译像Pillow之类的图书馆时,如何更改Python dll的名称
- 波科C++图书馆:"Not found: mysql"