You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GMock中WillByDefault在预期调用匹配场景下异常触发的问题咨询

GMock中WillByDefault在预期调用匹配场景下异常触发的问题咨询

我仔细看了你的代码和问题描述,终于找到问题的核心了——你踩中了GMock中一个容易被忽略的细节:当EXPECT_CALL没有显式指定动作时,它的默认行为是执行DoDefault,也就是触发ON_CALL中定义的WillByDefault动作,而不是你以为的“只有未匹配的调用才会触发默认动作”。

问题具体分析

你的代码里,三个EXPECT_CALL都只添加了RetiresOnSaturation()修饰符,但没有指定任何实际执行的动作。GMock对于这种情况,会默认使用DoDefault动作,也就是调用你在ON_CALL里设置的WillByDefault(testing::Throw(...))。

这就导致了:

  1. 当第一个mock.foo(1)被调用时,虽然它匹配了第一个EXPECT_CALL,但因为没有显式动作,就会执行抛出异常的默认动作,直接终止了do_test函数,后面的mock.foo(2)和mock.foo(1)根本没被调用,最终出现“2个未满足的期望”的错误。
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 10:30:29