Google Test中调用mock shared_ptr方法触发段错误的问题
问题原因分析
- ON_CALL匹配条件不匹配:最常见的根源是CoreBuilder的
createWindow方法签名(比如参数类型/数量、是否为const成员函数)与GMock配置的期望不匹配,导致GMock没有触发预设的返回逻辑,最终返回shared_ptr的默认空值。 - CoreBuilder传递方式错误:如果Engine构造函数接收的是CoreBuilder的值传递,会导致mock对象被拷贝,原mock实例的ON_CALL配置不会作用到拷贝后的对象上。
- unique_ptr的所有权处理失误:使用
unique_ptr时,若未正确用ByMove转移所有权,会导致返回空指针;多次调用时未生成新的mock对象,也会因所有权已转移而返回空。
正确的Mock智能指针配置示例
先定义基础接口与Mock类:
// 核心接口定义 class Window { public: virtual ~Window() = default; virtual bool isOpen() const = 0; }; class CoreBuilder { public: virtual ~CoreBuilder() = default; virtual std::shared_ptr<Window> createWindow() = 0; // 其他接口:createClock、createStateMachine等 }; // Mock类实现 class WindowMock : public Window { public: MOCK_METHOD(bool, isOpen, (), (const, override)); }; class CoreBuilderMock : public CoreBuilder { public: MOCK_METHOD(std::shared_ptr<Window>, createWindow, (), (override)); // 对应其他接口的MOCK_METHOD };
shared_ptr场景的测试代码
TEST(EngineTest, IsWindowOpen_ReturnsCorrectValue) { // 1. 创建mock对象并管理生命周期 auto mockWindow = std::make_shared<WindowMock>(); CoreBuilderMock mockBuilder; // 2. 严格匹配方法签名配置返回逻辑 ON_CALL(mockBuilder, createWindow()) .WillByDefault(Return(mockWindow)); // 3. 传递mock对象给Engine(注意用引用/指针,避免拷贝) Engine sut(mockBuilder); // 4. 配置WindowMock的方法期望 EXPECT_CALL(*mockWindow, isOpen()) .WillOnce(Return(true)); // 5. 执行测试断言 ASSERT_TRUE(sut.isWindowOpen()); }
unique_ptr场景的测试代码
TEST(EngineTest, UniquePtrMock_WorksCorrectly) { CoreBuilderMock mockBuilder; // 配置返回unique_ptr时必须用ByMove转移所有权 ON_CALL(mockBuilder, createWindow()) .WillByDefault(Return(ByMove(std::make_unique<WindowMock>()))); // 若需多次调用,每次生成新的mock对象 // ON_CALL(mockBuilder, createWindow()) // .WillRepeatedly(Return(ByMove(std::make_unique<WindowMock>()))); Engine sut(mockBuilder); // 后续测试逻辑... }
关键注意事项
- 严格匹配方法签名:检查CoreBuilder的
createWindow是否为const成员函数,若原接口是virtual std::shared_ptr<Window> createWindow() const = 0;,则Mock类的MOCK_METHOD也需标记为const,ON_CALL的写法也要完全对应。 - 禁止值传递Mock对象:Engine构造函数应接收CoreBuilder的引用或指针,避免拷贝导致Mock配置失效。
- 验证Mock调用情况:添加
EXPECT_CALL(mockBuilder, createWindow()).Times(1);,确认Engine在构造时确实调用了createWindow方法,排查构造逻辑是否存在问题。 - unique_ptr所有权唯一:使用
ByMove后,原unique_ptr会失效,若需多次返回,必须每次生成新的Mock对象。
内容的提问来源于stack exchange,提问作者Patello
相关产品推荐
相关产品推荐

