GMock中WillByDefault在预期调用匹配场景下异常触发的问题咨询
GMock中WillByDefault在预期调用匹配场景下异常触发的问题咨询
我仔细看了你的代码和问题描述,终于找到问题的核心了——你踩中了GMock中一个容易被忽略的细节:当EXPECT_CALL没有显式指定动作时,它的默认行为是执行DoDefault,也就是触发ON_CALL中定义的WillByDefault动作,而不是你以为的“只有未匹配的调用才会触发默认动作”。
问题具体分析
你的代码里,三个EXPECT_CALL都只添加了RetiresOnSaturation()修饰符,但没有指定任何实际执行的动作。GMock对于这种情况,会默认使用DoDefault动作,也就是调用你在ON_CALL里设置的WillByDefault(testing::Throw(...))。
这就导致了:
- 当第一个
mock.foo(1)被调用时,虽然它匹配了第一个EXPECT_CALL,但因为没有显式动作,就会执行抛出异常的默认动作,直接终止了do_test函数,后面的mock.foo(2)和mock.foo(1)根本没被调用,最终出现“2个未满足的期望”的错误。 - 当你把默认动作改成打印时,每个
EXPECT_CALL的调用都会执行打印动作,但do_test能完整执行完三个调用,三个EXPECT_CALL都被匹配并退休,所以StrictMock没有检测到未预期的调用,测试通过,但因为每个调用都触发了打印,所以会输出3次信息。
解决方案
要解决这个问题,你只需要给每个EXPECT_CALL显式指定一个空动作,覆盖默认的DoDefault即可。对于void类型的方法,最简单的就是用testing::Return()(它对void方法是合法的,不会执行任何操作),或者用一个空的lambda表达式:
修改后的EXPECT_CALL部分代码如下:
EXPECT_CALL(mock, foo(1)).RetiresOnSaturation().WillOnce(testing::Return()); EXPECT_CALL(mock, foo(2)).RetiresOnSaturation().WillOnce(testing::Return()); EXPECT_CALL(mock, foo(1)).RetiresOnSaturation().WillOnce(testing::Return());
这样修改后:
- 每个
EXPECT_CALL匹配时会执行空动作,不会触发ON_CALL的默认行为; StrictMock依然会保证所有调用都被正确匹配,未预期的调用会直接触发失败;EXPECT_NO_THROW(do_test(mock))会正常通过,因为三个调用都不会抛出异常。
另外补充一点:如果你只是想对未匹配的调用提前终止测试,其实StrictMock本身就会对未预期的调用立即触发致命失败,不需要额外设置WillByDefault(Throw)。这个默认行为已经能满足你“终止测试 early”的需求。
内容来源于stack exchange
相关产品推荐
相关产品推荐

