GMock使用问题:TIMES报错、Mock行为修改及测试失败排查
一、基础Mock场景问题
待Mock的基类与Mock类定义
基类代码:
class Base{ public: void virtual func() { sleep(3); } };
Mock类代码:
class Mock: public Base{ public: MOCK_METHOD(void, func, (), (override)); };
测试用例代码:
TEST(TestMockSanity, AbleToMock) { Mock mock; EXPECT_CALL(mock, func()); }
问题1:语法错误:class testing::internal::TypedExpectation<void()> has no member named ‘TIMES’
解决方法:
- TIMES是GMock的约束宏,需通过
testing::Times()方式调用,正确链式写法示例:EXPECT_CALL(mock, func()).Times(testing::AtLeast(1)); - 注意:必须使用
testing::命名空间下首字母大写的Times,而非全大写的TIMES,否则会触发语法错误。
问题2:如何将Mock类中func的实现改为sleep(0)?
推荐解决方法:使用ON_CALL设置默认行为,既保留Mock的验证能力,又自定义实现:
TEST(TestMockSanity, AbleToMock) { Mock mock; ON_CALL(mock, func()).WillByDefault([](){ sleep(0); }); // 若需验证调用,可保留EXPECT_CALL EXPECT_CALL(mock, func()); mock.func(); }
也可在Mock类中直接重写,但会失去Mock的灵活性,仅适合固定默认场景:
class Mock: public Base{ public: MOCK_METHOD(void, func, (), (override)); void func() override { sleep(0); } };
二、Mock测试失败问题
相关代码文件
./real.hpp
class Real { public: Real(){}; virtual ~Real(){}; virtual int run(); virtual int dont_run(); };
./real.cpp
#include "real.hpp" int Real::run() { return 0; }; int Real::dont_run() { return 1; };
./meson.build
project( 'gtest', 'cpp', default_options : [ 'cpp_std=c++14', ], ) sources = files('main.cpp', 'real.cpp') executable( 'real', sources, install : false, ) executable( 'mock', files('real.cpp', 'mock.cpp'), dependencies: [dependency('gtest'), dependency('gmock')], install : false, )
./mock.cpp
#include "gmock/gmock.h" // MOCK_METHOD #include "gtest/gtest.h" // TEST #include "real.hpp" class MockReal : public Real { public: MOCK_METHOD(int, run, (), (override)); MOCK_METHOD(int, dont_run, (), (override)); void delegate(){ ON_CALL(*this, run).WillByDefault([this](){ return 1; }); ON_CALL(*this, dont_run).WillByDefault([this](){ return 2; }); } }; TEST(TestMockSanity, AbleToMock) { MockReal mock; EXPECT_EQ(0, mock.run()); EXPECT_EQ(1, mock.dont_run()); mock.delegate(); EXPECT_EQ(1, mock.run()); EXPECT_EQ(2, mock.dont_run()); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
测试运行结果
[==========] Running 1 test from 1 test suite. [----------] Global test environment set-up. [----------] 1 test from TestMockSanity [ RUN ] TestMockSanity.AbleToMock GMOCK WARNING: Uninteresting mock function call - returning default value. Function call: run() Returns: 0 NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md#knowing-when-to-expect for details. GMOCK WARNING: Uninteresting mock function call - returning default value. Function call: dont_run() Returns: 0 NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md#knowing-when-to-expect for details. ../mock.cpp:24: Failure Expected equality of these values: 1 mock.dont_run() Which is: 0 GMOCK WARNING: Uninteresting mock function call - taking default action specified at: ../mock.cpp:11: Function call: run() Returns: 1 NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md#knowing-when-to-expect for details. GMOCK WARNING: Uninteresting mock function call - taking default action specified at: ../mock.cpp:14: Function call: dont_run() Returns: 2 NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md#knowing-when-to-expect for details. [ FAILED ] TestMockSanity.AbleToMock (0 ms) [----------] 1 test from TestMockSanity (0 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test suite ran. (0 ms total) [ PASSED ] 0 tests. [ FAILED ] 1 test, listed below: [ FAILED ] TestMockSanity.AbleToMock 1 FAILED TEST
问题原因与解决方法
核心问题分析
- Mock默认行为未调用基类方法:GMock覆盖基类虚函数后,默认返回类型的默认值(int类型返回0),而非调用基类
dont_run()的返回值1,导致断言失败。 - 构建配置符号冲突:
meson.build中mock可执行文件同时链接real.cpp和mock.cpp,真实实现与Mock方法符号冲突,导致Mock机制无法正常工作。
解决步骤
修改Mock类,默认调用基类实现:
在Mock类构造函数中设置默认行为为调用基类方法,满足测试预期:class MockReal : public Real { public: MOCK_METHOD(int, run, (), (override)); MOCK_METHOD(int, dont_run, (), (override)); MockReal() { // 默认调用基类方法 ON_CALL(*this, run).WillByDefault([this](){ return Real::run(); }); ON_CALL(*this, dont_run).WillByDefault([this](){ return Real::dont_run(); }); } void delegate(){ ON_CALL(*this, run).WillByDefault([this](){ return 1; }); ON_CALL(*this, dont_run).WillByDefault([this](){ return 2; }); } };修改meson.build,消除符号冲突:
编译测试程序时无需链接real.cpp,Mock类已继承Real的声明,调用基类实现可直接通过Real::method()完成:executable( 'mock', files('mock.cpp'), dependencies: [dependency('gtest'), dependency('gmock')], install : false, )验证结果:
修改后,测试用例中:- 调用
delegate()前,mock.run()返回基类的0,mock.dont_run()返回基类的1 - 调用
delegate()后,run()返回1,dont_run()返回2
所有断言将通过,GMOCK的"Uninteresting mock function call"警告也会消失。
- 调用
内容的提问来源于stack exchange,提问作者CIsForCookies
相关产品推荐
相关产品推荐

