为何GTest会生成Uninteresting mock function call警告?
问题
我给一个使用单例模式的类编写了GTest测试,该类通过调用公共成员实例的方法读取文件。我Mock了这个公共成员所属的类,并用ON_CALL手动填充JSON对象(而非从文件读取)。测试已通过,但输出中出现了Uninteresting mock function call警告,我无法理解该警告的产生原因,想知道是否可以忽略它,或是有解决该问题的方法。
完整代码
#include <gtest/gtest.h> #include <gmock/gmock.h> #include <cstddef> #include <filesystem> #include <fstream> #include <iostream> #include "json.hpp" using json = nlohmann::json; class MockedUtil { public: MockedUtil(){}; ~MockedUtil(){}; MOCK_METHOD(bool, readJSONFile, (const std::string &filePath, json &j)); MOCK_METHOD(bool, writeJSONFile, (const std::string &filePath, const json &j)); }; template<typename T> class Singleton { public: static T& get() { static T s(token{}); // return the instance return s; } // copy constructor Singleton(const Singleton&) = delete; // assignment operator Singleton& operator=(const Singleton) = delete; // move constructor Singleton(const Singleton&&) = delete; // Move assign Singleton& operator=(const Singleton&&) = delete; protected: // constructor Singleton(); // destructor virtual ~Singleton(); struct token {}; }; template<typename T> Singleton<T>::Singleton() {} template<typename T> Singleton<T>::~Singleton() {} class MyTest_mockfunctioncall_Test; class ConcreteSingleton : public Singleton<ConcreteSingleton> { private: FRIEND_TEST(::MyTest, mockfunctioncall); std::string private_key; int val = -1; public: ConcreteSingleton(token){}; MockedUtil wrapper; bool readJSON(const std::string& settings, json& my_json) { this->private_key = "MyKey"; const std::string path {"MyJson.json"}; bool result = wrapper.readJSONFile(path, my_json); if (!result) { std::cout<<"Unable to read json file\n"; return false; } if (!my_json[this->private_key].contains(settings)) { std::cout<<"Setting is not present in my_json\n"; std::cout<< my_json.dump(1, '\t') << "\n\n"; return false; } my_json[settings] = my_json[this->private_key][settings]; return true; } }; class ClassToBeTested{ public: ClassToBeTested() = default; int value; ~ClassToBeTested() = default; void foo() { value = -1; std::cout<<__FILE__<<":"<<__LINE__<<"; value: "<<value<<std::endl; json my_json = nullptr; std::cout<<" before calling\n"; const std::string key {"my_key"}; bool result = ConcreteSingleton::get().readJSON(key,my_json); if(result){ value = my_json[key]; std::cout<<"LINE COVERED\n"; } else { std::cout<<"LINE NOT COVERED\n"; } std::cout<<__FILE__<<":"<<__LINE__<<"; value: "<<value<<std::endl; } }; TEST(MyTest, mockfunctioncall) { auto& singleton = ConcreteSingleton::get(); ClassToBeTested object; json my_json = nullptr; const std::string mystr{"MyJson"}; ON_CALL( singleton.wrapper, readJSONFile(::testing::_, ::testing::_)) .WillByDefault( [&](const std::string& filePath, json& j) { std::cout<<"inside lambda\n"; j = R"( {"MyKey": {"my_key": 2}} )"_json;; return true; }); object.foo(); EXPECT_EQ(object.value, 2); }
测试输出
test_file.cpp:105; value: -1 before calling inside lambda GMOCK WARNING: Uninteresting mock function call - taking default action specified at: test_file.cpp:128: Function call: readJSONFile(@0x7ffe1fea0ad0 "MyJson.json", @0x7ffe1fea0b60 null) Returns: true 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/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details. LINE COVERED test_file.cpp:118; value: 2
分析与解决
警告原因
这个警告的核心是:你用ON_CALL为Mock方法设置了默认行为,但没有显式声明你期望该Mock方法被调用。GMock会将这种"有默认行为但未被预期的调用"判定为"无意义调用",即便你的测试逻辑正常执行,也会抛出该提示。
处理方案
你有两种可行的处理方式:
1. 直接忽略(确认调用符合预期时)
如果这个readJSONFile调用是你测试流程中明确需要的步骤,完全可以忽略该警告。GMock的提示也明确说明,只要调用是合理的,就无需处理。
2. 消除警告的具体方法
方法一:用EXPECT_CALL明确预期调用
将ON_CALL替换为EXPECT_CALL,明确告知GMock你期望该方法被调用的次数,同时保留原有行为逻辑:
EXPECT_CALL(singleton.wrapper, readJSONFile(::testing::_, ::testing::_)) .Times(1) // 明确预期调用1次 .WillOnce( [&](const std::string& filePath, json& j) { std::cout<<"inside lambda\n"; j = R"( {"MyKey": {"my_key": 2}} )"_json;; return true; });
如果不需要限制调用次数,可以用Times(::testing::AnyNumber())替代Times(1)。
方法二:使用NiceMock包装Mock类
NiceMock会自动屏蔽所有"无意义调用"的警告,适合只需要设置默认行为、不需要严格校验调用次数的场景。只需修改ConcreteSingleton中的成员定义:
// 原代码 MockedUtil wrapper; // 修改为 ::testing::NiceMock<MockedUtil> wrapper;
内容的提问来源于stack exchange,提问作者roschach
相关产品推荐
相关产品推荐

