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

如何使用gMock测试智能指针持有的多态接口类?

解决gMock测试多态注入对象的问题

核心问题排查与修复步骤

1. 确保Mock类定义完全符合gMock规则

你的MockDraw类必须严格匹配DrawI的接口签名,使用gMock的MOCK_METHOD宏声明所有虚函数(包括纯虚和非纯虚)。签名不匹配会导致gMock无法正确拦截方法调用。

正确的Mock类定义示例:

#include <gmock/gmock.h>

struct MockDraw : public DrawI {
    // 匹配原接口的point方法(非纯虚也需Mock)
    MOCK_METHOD(void, point, (int x1, int y1), (override));
    // 匹配原接口的纯虚line方法
    MOCK_METHOD(void, line, (int x1, int y1, int x2, int y2), (override));
};

必须加上override关键字确保签名完全匹配,gMock会严格检查方法的参数、返回值、const修饰符(若有)是否与原接口一致。

2. 验证DeviceIO内部是否正确持有并使用传入的DrawI实例

检查DeviceIO的实现,确保它没有在内部创建新的DrawI实例,而是直接使用构造函数传入的shared_ptr:

struct DeviceIO {
    std::shared_ptr<DrawI> _drawer;
    OtherProperties _props;

    DeviceIO(std::shared_ptr<DrawI> drawer, OtherProperties props)
        : _drawer(std::move(drawer)), _props(std::move(props)) {}

    void draw(Type t, Info i) {
        // 确保此处调用的是传入的_drawer实例的方法
        if (t == Point) {
            _drawer->point(i.x, i.y); // 根据实际Info结构调整参数
        }
        // 其他绘图逻辑...
    }

    // 其他方法...
};

如果DeviceIO内部替换了_drawer指针,gMock的调用拦截自然不会生效。

3. 修正测试代码的细节

你的测试框架逻辑正确,但需注意两个关键细节:

  • EXPECT_CALL必须在调用io.draw()之前设置,gMock的调用期望是前置声明的。
  • 若需要精确匹配参数,可使用gMock的匹配器(如Eq()),默认是宽松匹配任意参数。

修正后的测试代码:

TEST(DeviceIOTest, DrawPointTriggersMockCall) {
    // 创建Mock实例
    auto painter = std::make_shared<MockDraw>();
    // 注入到DeviceIO
    DeviceIO io(painter, {/* 初始化OtherProperties */});

    // 设置期望:point方法被调用1次,参数为任意值
    EXPECT_CALL(*painter, point(::testing::_, ::testing::_)).Times(1);

    // 执行被测试方法
    EXPECT_NO_THROW(io.draw(Point, {/* 构造对应的Info对象 */}));
}

常见坑点总结

  • 签名不匹配:Mock方法的参数类型、返回值、const修饰符必须与原接口完全一致,否则gMock无法识别。
  • 实例不唯一:确保DeviceIO使用的是你创建的Mock实例,而非内部新建的其他DrawI实现。
  • 期望顺序错误:EXPECT_CALL必须在触发调用的代码之前执行,否则gMock会判定期望未被满足。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:55:19