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

如何在gmock中搭配派生类std::shared_ptr使用SaveArgPointee

问题原因说明

首先纠正两个认知误区:

  • 用SaveArg保存shared_ptr类型参数完全不存在悬垂指针风险,shared_ptr拷贝时会自动增加引用计数,只要接收变量在作用域内,指向的对象就不会被提前释放
  • SaveArgPointee是对参数解引用后保存值,要求指向的类型可拷贝赋值,你之前报错要么是类型不匹配,要么是消息类没有可访问的拷贝构造/赋值运算符,要么是没有传入变量的指针地址

推荐解决方案:直接用SaveArg保存shared_ptr

这是最稳妥、无额外限制的方案,直接匹配sendMessage的参数类型即可:

TEST(SomeClassTest, writesMessageToSocket){
   MockTcp mockTcp;
   SomeClass sc(mockTcp);
   
   // 声明和sendMessage参数同类型的shared_ptr即可
   std::shared_ptr<BaseMessage> msgArg;
   // SaveArg<0>表示保存第0位参数本身,注意要传入变量的指针
   EXPECT_CALL(mockTcp, sendMessage(_)).Times(1).WillOnce(::testing::SaveArg<0>(&msgArg));
   const auto derivedMsg = std::make_shared<DerivedMessage>();
   sc.writeDataToRemote(derivedMsg);
   
   // 后续校验逻辑示例
   auto derivedArg = std::dynamic_pointer_cast<DerivedMessage>(msgArg);
   ASSERT_NE(derivedArg, nullptr);
   // 可以继续校验derivedArg的data()返回值、内部成员等逻辑
}

备选方案:用SaveArgPointee保存对象副本

如果你确实需要保存消息对象的独立副本,需要保证DerivedMessage可拷贝,代码实现如下:

TEST(SomeClassTest, writesMessageToSocket){
   MockTcp mockTcp;
   SomeClass sc(mockTcp);
   
   // 必须用具体子类类型声明变量,不能用抽象基类BaseMessage
   DerivedMessage msgArg;
   EXPECT_CALL(mockTcp, sendMessage(_))
       .Times(1)
       .WillOnce(::testing::SaveArgPointee<0>(&msgArg));
   const auto derivedMsg = std::make_shared<DerivedMessage>();
   sc.writeDataToRemote(derivedMsg);
   
   // 直接校验msgArg的内容即可
}

内容的提问来源于stack exchange,提问作者El_Mewo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:15:01