假设我们有以下课程A
和B
:
class A
{
virtual void Init() { DoSomething(); }
};
class B : public A
{
virtual void Init() { DoSomethingSpecial(); A::Init(); }
};
在我们的单元测试中,我们只想测试B
,即使用Hippomocks进行测试,调用B::Init()
实际上会调用DoSomethingSpecial()
:
B* b_p = new B();
m_mockRepository_p->ExpectCall(b_p, DoSomethingSpecial);
b_p->Init();
现在我们不希望所有来自A
Init()
的来电,所以我们想写下这样的内容:
m_mockRepository_p->ExpectCall(b_p, A::Init);
最后的期望会导致一个未处理的异常,我认为这是可以的,因为我们正在调用我们想要的基本版本调用的方法。将b_p
投射到A
无济于事。
该特定用例是否有任何解决方案?
答案 0 :(得分:0)
......这是一个有趣的问题。我认为没有解决方案。对A :: Init的调用不是通过虚函数表完成的(因为你明确知道要调用哪一个),所以它属于非虚函数,你无法模拟。
添加这个的一个复杂因素是,如果你在B上获取了A :: Init的地址,你仍然会得到vtable指针,所以你甚至无法替换该函数(比如说,使用C函数模拟逻辑)。
我只能推荐通用的重构解决方案来解决这个问题 - 使A和B独立的类,使B包含A(私有继承)或从A和B中提取接口并将B转换为装饰器。最后听起来最好,但这取决于A和B究竟是什么......