使用Gmock/Gtest测试不可拷贝对象时Mock方法未触发问题排查
问题分析与解决方案
你的问题核心出在Mock测试的期望设置逻辑上——gmock不会自动帮你验证方法调用,必须显式声明你期望的行为,而且设置顺序直接影响验证结果。
错误原因拆解
- 缺少
EXPECT_CALL语句:你提供的MockMonster测试用例里,只创建了Mock对象和Controller并调用了Explode(),但没有告诉gmock你期望mockmonster::Explode()被调用。gmock只有在收到明确的EXPECT_CALL指令后,才会跟踪并验证方法的调用情况。 - 期望设置顺序错误(如果你实际代码里写了
EXPECT_CALL但位置不对):如果EXPECT_CALL是在c.Explode()之后才设置的,gmock无法捕获到之前已经发生的调用,会误认为方法从未被执行,从而抛出你看到的错误。
修正后的Mock测试用例
#include <gmock/gmock.h> #include <gtest/gtest.h> #include "controller.h" #include "iview.h" class mockmonster : public IView { public: MOCK_METHOD0(Explode, void()); // gmock会自动生成合规的虚析构函数,无需手动声明 }; TEST(MockMonster, Explode) { mockmonster h; // 第一步:先设置期望——明确告诉gmock你希望Explode被调用至少一次 EXPECT_CALL(h, Explode()).Times(::testing::AtLeast(1)); // 第二步:创建Controller并传入Mock对象 Controller c(&h); // 第三步:触发方法调用 c.Explode(); } TEST(HobGoblin, Explode) { hobgoblin h; Controller c(&h); c.Explode(); }
关键细节说明
- 期望设置顺序:必须在触发方法调用前设置
EXPECT_CALL,gmock从设置时刻开始跟踪方法调用,晚于调用的期望会被忽略。 - 调用次数匹配:
Times(::testing::AtLeast(1))表示期望方法被调用至少一次,你也可以用Times(1)严格匹配调用次数,甚至省略Times(默认期望被调用一次)。 - Mock类简化:gmock的
MOCK_METHOD宏会自动处理虚函数和析构函数逻辑,所以mockmonster不需要手动声明virtual ~mockmonster()。
为什么真实对象测试正常?
真实的hobgoblin对象的Explode()有实际行为(修改生命值+输出日志),你可以通过观察输出或检查状态判断方法是否被调用;但Mock对象本身没有实际行为,只能依赖gmock的期望机制验证调用情况,因此必须显式设置期望。
内容的提问来源于stack exchange,提问作者agent_bean
相关产品推荐
相关产品推荐

