如何在GMock测试中使用Json::Value类对象
针对你的问题,我来详细说明如何在GMock测试中使用Json::Value类对象,结合你给出的LoadLibTaskImpl和LoadLibTask代码场景,具体步骤和示例如下:
在GMock测试中使用Json::Value类对象的方法
1. 先定义对应的Mock类
首先需要为抽象基类LoadLibTaskImpl创建Mock类,这样我们才能在测试中模拟load_mal_lib方法的行为,同时处理Json::Value&类型的引用参数:
#include <gmock/gmock.h> #include "LoadLibTaskImpl.h" // 替换为你实际的基类头文件路径 #include <Json/Json.h> // 引入Json库头文件 class MockLoadLibTaskImpl : public LoadLibTaskImpl { public: // 用GMOCK_METHOD宏声明mock方法,参数列表与原纯虚函数完全一致 MOCK_METHOD(SharedLibrary*, load_mal_lib, (std::string, std::string, Json::Value&), (override)); };
2. 编写测试用例:处理Json::Value的常见场景
场景1:验证传入的Json::Value内容是否符合预期
如果需要检查load_mal_lib被调用时,传入的Json::Value参数内容是否符合预期,可以使用GMock的匹配器(比如Property)来校验Json对象的键值对:
TEST(LoadLibTaskTest, LoadMalLibReceivesCorrectJson) { // 1. 初始化Mock对象 MockLoadLibTaskImpl mock_task; // 2. 准备预期的Json对象 Json::Value expected_json; expected_json["lib_category"] = "malicious"; expected_json["signature"] = "abc123"; // 3. 设置调用期望:忽略前两个string参数,校验第三个Json参数的内容 EXPECT_CALL(mock_task, load_mal_lib( testing::_, // 匹配任意第一个string参数 testing::_, // 匹配任意第二个string参数 // 校验Json对象是否包含预期的键值对 testing::AllOf( testing::Property(&Json::Value::operator[], Json::Value("malicious")), testing::Property(&Json::Value::operator[], Json::Value("abc123")) ) )) .WillOnce(testing::Return(new SharedLibrary("test_mal_lib"))); // 设置方法返回值 // 4. 触发mock方法调用(这里直接调用,实际测试中可能通过被测代码间接触发) Json::Value actual_json; actual_json["lib_category"] = "malicious"; actual_json["signature"] = "abc123"; auto lib = mock_task.load_mal_lib("/tmp/lib", "test.so", actual_json); // 5. 验证返回值(可选) ASSERT_NE(lib, nullptr); delete lib; // 清理内存 }
场景2:模拟方法修改传入的Json::Value引用
如果load_mal_lib方法会修改传入的Json::Value对象(比如填充加载状态、错误码等),可以用testing::SetArgReferee来设置参数被修改后的内容:
TEST(LoadLibTaskTest, LoadMalLibModifiesJsonParameter) { MockLoadLibTaskImpl mock_task; // 设置期望:调用时修改第三个引用参数的内容 EXPECT_CALL(mock_task, load_mal_lib(testing::_, testing::_, testing::_)) .WillOnce(DoAll( // 给第三个参数(索引为2)设置修改后的内容 testing::SetArgReferee<2>([](Json::Value& json) { json["load_status"] = "success"; json["error_code"] = 0; }), testing::Return(new SharedLibrary("test_mal_lib")) )); // 调用方法并获取修改后的Json对象 Json::Value result_json; auto lib = mock_task.load_mal_lib("/tmp/lib", "test.so", result_json); // 验证Json对象是否被正确修改 ASSERT_EQ(result_json["load_status"].asString(), "success"); ASSERT_EQ(result_json["error_code"].asInt(), 0); delete lib; }
3. 结合你的LoadLibTask类进行测试
如果LoadLibTask的load_library方法内部会调用load_mal_lib,建议通过依赖注入的方式让LoadLibTask依赖于LoadLibTaskImpl指针,这样测试时可以替换为Mock对象:
先调整LoadLibTask的实现(支持依赖注入)
class LoadLibTask: public LoadLibTaskImpl { public: // 新增构造函数,注入LoadLibTaskImpl实现 explicit LoadLibTask(LoadLibTaskImpl* impl) : m_impl(impl) {} ~LoadLibTask() override { delete m_impl; } inline SharedLibrary *load_library(string cm_lib_path, string lib_name) override { lib_name = cm_lib_path + "/" + lib_name; Json::Value load_config; // 调用注入的实现类的load_mal_lib方法 return m_impl->load_mal_lib(cm_lib_path, lib_name, load_config); } private: LoadLibTaskImpl* m_impl; };
编写对应的测试用例
TEST(LoadLibTaskTest, LoadLibraryDelegatesToMock) { // 1. 创建Mock对象并注入到LoadLibTask中 MockLoadLibTaskImpl* mock_impl = new MockLoadLibTaskImpl(); LoadLibTask task(mock_impl); // 2. 设置Mock的调用期望 EXPECT_CALL(*mock_impl, load_mal_lib( testing::StrEq("/usr/lib"), // 匹配第一个参数为"/usr/lib" testing::StrEq("/usr/lib/malicious.so"), // 匹配第二个参数为拼接后的路径 testing::_ // 忽略第三个Json参数 )) .WillOnce(testing::Return(new SharedLibrary("malicious.so"))); // 3. 调用被测方法 auto lib = task.load_library("/usr/lib", "malicious.so"); // 4. 验证结果 ASSERT_NE(lib, nullptr); delete lib; }
内容的提问来源于stack exchange,提问作者H.Singh
相关产品推荐
相关产品推荐

