ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

如何用 GoogleMock NiceMock 和 StrictMock 控制 uninteresting call 警告

2026/9/12 16:48:59 拓冰建站 浏览量
如何用 GoogleMock NiceMock 和 StrictMock 控制 uninteresting call 警告 如何用 GoogleMock NiceMock 和 StrictMock 控制 uninteresting call 警告【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest在写 GoogleMock 测试时一个常见的现象是mock 对象的某个方法没有设置任何EXPECT_CALL却仍然被被测代码调用了。gMock 把这种调用称为 uninteresting call默认的 mock 对象行为等价于NaggyMock会执行该方法的默认动作可用ON_CALL()指定并额外打印一条 uninteresting 警告。这条警告本身不是错误但有时你希望彻底静默它有时又希望它直接让测试失败。本文基于 GoogleMock 实战手册 和 参考文档说明如何分别用NiceMockT和StrictMockT来控制这两类行为以及各自的适用边界。动手前先分清 uninteresting call 和 unexpected call这两种调用在 gMock 中是完全不同的概念见 The Nice, the Strict, and the Naggy 一节的解释uninteresting call方法x.Y(...)上一个EXPECT_CALL(x, Y(...))都没有设置说明测试对该方法本身不关心。按 gMock 的规则不说什么就意味着没有约束所以 uninteresting call 默认不是错误只产生警告——因为可能暗示测试作者忘了写约束。unexpected call已经设置了某些EXPECT_CALL(x, Y(...))但没有一个与本次调用匹配。unexpected call总是错误因为被测代码的行为不符合测试预期。NiceMock和StrictMock只作用于 uninteresting call不影响 unexpected call 的严重级别。这一点直接决定了后文两种包装的用法nice mock 不会让原本失败的测试通过strict mock 则可能改变测试结果。用 NiceMock 静默 uninteresting call 警告NiceMockT表示一个会对 uninteresting call 抑制警告的 mock 对象见 NiceMock 参考条目。它是T的子类可以放在任何接受T的地方使用同时它继承了T的构造函数所以可以接受T构造函数所需的任意实参。假设测试原本这样写TEST(...) { MockFoo mock_foo; EXPECT_CALL(mock_foo, DoThis()); ... code that uses mock_foo ... }只要mock_foo上DoThis()之外的方法被调用就会收到警告。改用NiceMockMockFoo即可抑制这类警告using ::testing::NiceMock; TEST(...) { NiceMockMockFoo mock_foo; EXPECT_CALL(mock_foo, DoThis()); ... code that uses mock_foo ... }如果MockFoo的构造函数需要参数直接透传即可using ::testing::NiceMock; TEST(...) { NiceMockMockFoo mock_foo(5, hi); // Calls MockFoo(5, hi). EXPECT_CALL(mock_foo, DoThis()); ... code that uses mock_foo ... }替代路径如果你只想对个别方法关闭警告而不想静默整个 mock 对象手册给出的做法是为该方法补一条EXPECT_CALL(...).Times(AnyNumber())例如using ::testing::_; using ::testing::AnyNumber; EXPECT_CALL(mock_registry, GetDomainOwner(_)) .Times(AnyNumber()); // catches all other calls to this method.手册同时明确警告不要为了消除警告而盲目地加EXPECT_CALL(...)不带Times(AnyNumber())那会造出一个难以维护的测试。判断依据手册指出nice mock 只是话少了除此之外与默认 mock 行为一致——如果某个测试用默认 mock 会失败换成 nice mock 一样会失败反之亦然。所以验证NiceMock是否生效看的是警告消失且测试结果不变而不是测试结果发生变化。用 StrictMock 把 uninteresting call 变成失败StrictMockT的用法与NiceMockT类似见 StrictMock 参考条目区别是它把所有 uninteresting call 从警告升级为测试失败using ::testing::StrictMock; TEST(...) { StrictMockMockFoo mock_foo; EXPECT_CALL(mock_foo, DoThis()); ... code that uses mock_foo ... // The test will fail if a method of mock_foo other than DoThis() // is called. }只要被测代码调用了mock_foo上除DoThis()之外的任何方法测试就会失败。与 nice mock 不同手册明确指出把 mock 改成 strict 可能会改变测试结果这正是使用它的目的也是使用它需要小心的原因。一个典型的配合场景来自手册中uninteresting vs unexpected一节只想验证GetDomainOwner(google.com)的行为但允许该方法用其他参数被调用。标准做法是加一条兜底EXPECT_CALLEXPECT_CALL(mock_registry, GetDomainOwner(_)) .Times(AnyNumber()); // catches all other calls to this method. EXPECT_CALL(mock_registry, GetDomainOwner(google.com)) .WillRepeatedly(Return(Larry Page));注意两条EXPECT_CALL的先后顺序很重要新写的EXPECT_CALL优先于旧写的生效。这里_是匹配任意值的通配 matcher——GetDomainOwner(google.com)命中第二条其余参数命中第一条。必须了解的三个限制NiceMock和StrictMock都有一些 C 层面带来的限制使用前的 mock 类设计要对照检查只对被测类内直接用MOCK_METHOD宏定义的 mock 方法生效。如果 mock 方法定义在T的基类中nice或strict修饰对它们可能不起作用具体取决于编译器。不支持嵌套。NiceMockStrictMockMockFoo这类嵌套写法不被支持。参考文档也相应限制NiceMockT、NaggyMockT、StrictMockT的模板参数T不能是另一个NiceMock、NaggyMock或StrictMock。T的析构函数如果不是 virtual修饰可能不生效文档明确说明这一点是已知的局限。什么时候选哪种手册对选择给出了明确的倾向性建议可以直接对照执行naggy mock当前默认在开发或调试测试时使用警告加默认行为帮你留意是否有该设约束而未设约束的调用。nice mock多数时候使用避免重构代码时因内部交互变化被警告刷屏。strict mock只作为最后手段。原因是 naggy 或 strict mock 倾向让测试更脆、更难维护当你重构代码而不改变外部可见行为时理想情况下测试不该跟着改但代码一旦与 naggy mock 交互可能开始被警告刷屏与 strict mock 交互则测试直接失败、被迫修改。验证与后续排查仓库自带针对该行为的测试文件 gmock-nice-strict_test.cc可以结合它观察三种 mock 在相同调用序列下的表现差异。日常验证时可以按上面的判断依据对照换成NiceMock后uninteresting call 警告消失测试结果与原 mock 一致换成StrictMock后故意触发一条未设EXPECT_CALL的调用测试应当失败若仍看到 Uninteresting function call encountered - default action taken.. 之类的警告gmock_faq.md 解释它只是提示信息而非错误gMock 遇到 uninteresting call 时会 dump 调用栈从中可以定位是哪个 mock 方法、被怎样调用的。如果认为本不该出现 uninteresting call应顺着调用栈排查如果你本意是禁止调用却忘了写EXPECT_CALL(foo, Bar()).Times(0)按 Disallowing Unexpected Calls 一节补上显式的Times(0)约束而不是靠包装类兜底。限制方面再强调一次以上所有行为只针对方法上没有任何EXPECT_CALL的 uninteresting call已经设置了EXPECT_CALL但参数不匹配的 unexpected call 始终是错误NiceMock也不会减轻它的严重级别。【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考