Hippomocks值类型成员Mock无法触发异常问题求助
为什么Foo2的Mock会失败?如何在不修改类的前提下解决?
这是个典型的多态Mock在值类型和指针类型上的差异问题,我来帮你拆解清楚:
一、Foo1与Foo2的核心差异原因
Hippomocks的Mock机制完全依赖C++多态来工作:它创建的IBar*实际上是一个动态生成的IBar子类实例,这个子类重写了所有虚函数,加入了Hippomocks的调用拦截、预期检查逻辑。
1. Foo1(指针成员)能正常工作的原因
你把Mock对象的指针直接赋值给g->bar,当调用g->a()时,是通过指针调用虚函数,触发了多态机制——实际执行的是Mock子类重写的c()方法,自然能被Hippomocks拦截,抛出预期的异常。
2. Foo2(值类型成员)Mock失败的根源
你用memcpy(&g->bar, b, sizeof(*b))的操作完全搞错了方向:
g->bar是一个栈上的原始IBar值对象,而b指向的是堆上的Mock子类实例。memcpy只是把Mock对象的前sizeof(IBar)字节(也就是基类部分)复制到g->bar里,但这会破坏多态的核心——虚函数表(vtable):- 复制后
g->bar的类型依然是IBar,它的虚表指针并没有指向Mock子类的虚表,调用this->bar.c()时,还是执行原始IBar的c()方法,根本没走到Mock的拦截逻辑。 - 这种直接复制多态对象内存的操作本身就是未定义行为,可能导致虚表混乱、内存错误,完全不符合C++对象模型的规则。
- 复制后
这就是为什么你会看到HippoMocks::CallMissingException——Hippomocks记录了预期调用,但实际根本没人触发它。
二、不修改Foo2类的解决方案
Hippomocks专门提供了Inject方法,可以把Mock的虚表注入到一个已存在的对象实例中,完美解决值类型成员的Mock问题。修改你的test_a()函数如下:
void TestTest::test_a(){ /////// Test hippomock ///////////////////// MockRepository mocks; IBar *b = mocks.Mock<IBar>(); Foo2 *g = new Foo2(); // 关键:用Inject将Mock的虚表注入到g->bar对象中 mocks.Inject(&g->bar, b); mocks.ExpectCall(&g->bar, IBar::c).Throw(std::exception()); CPPUNIT_ASSERT_THROW (g->a(), std::exception); // 记得清理内存,避免泄漏 delete g; /////// Test hippomock end ///////////////////// }
为什么这个方法有效?
Inject方法会安全地修改目标对象(g->bar)的虚函数表指针,让它指向Hippomocks生成的Mock子类的虚表。这样即使g->bar是值类型的IBar对象,调用它的虚函数时,也会执行Mock的拦截逻辑,触发你预期的异常。
注意事项
- 确保目标对象的类是多态类型(也就是有至少一个虚函数,这里
IBar有虚析构和虚的c()方法,满足要求)。 - 测试结束后,
MockRepository会自动清理相关资源,不需要手动恢复目标对象的虚表(因为测试结束后g->bar也会被销毁)。
内容的提问来源于stack exchange,提问作者user7561458
相关产品推荐
相关产品推荐

