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

如何用GTest/GMock测试Parent类调用parent_method时是否触发member_method

解决方案:用模板类实现无多态、无动态分配的测试

想要在不使用多态和动态内存分配的前提下测试Parent的parent_method是否调用了Member的member_method,模板化你的Parent类是最优方案。它依赖编译期多态而非运行时虚函数,所有对象都可以在栈上创建,完美匹配你的需求。

步骤1:重构Parent为模板类

把Member的类型作为模板参数传入Parent,默认使用真实的Member类,这样正常业务代码不需要任何修改。同时我们可以保留栈上的成员变量,完全避免动态分配:

// 真实的Member类(无需修改)
class Member {
public:
    void member_method() {
        // 你的真实业务逻辑
    }
};

// 重构后的Parent模板类
template<typename MemberType = Member>
class Parent {
private:
    MemberType member_; // 栈上成员,无new/delete

public:
    // 如果Member需要构造参数,用完美转发支持任意初始化
    template<typename... Args>
    explicit Parent(Args&&... args) 
        : member_(std::forward<Args>(args)...) {}

    void parent_method() {
        member_.member_method(); // 调用成员的方法
    }

    // 为了测试能访问member_,可以提供getter或者把测试类设为友元
    MemberType& get_member() { return member_; }
    const MemberType& get_member() const { return member_; }
};

步骤2:编写GMock的Mock类

创建一个模拟Member行为的Mock类,用于测试:

#include <gmock/gmock.h>

class MockMember {
public:
    MOCK_METHOD(void, member_method, (), ()); // 模拟member_method
};

步骤3:编写GTest测试用例

用MockMember作为模板参数实例化Parent,然后验证调用:

#include <gtest/gtest.h>

TEST(ParentTest, ParentMethodCallsMemberMethod) {
    // 栈上创建Parent和MockMember,无动态分配
    Parent<MockMember> parent;
    MockMember& mock_member = parent.get_member();

    // 预期member_method被调用一次
    EXPECT_CALL(mock_member, member_method()).Times(1);

    // 触发测试行为
    parent.parent_method();
}

为什么这个方案符合你的要求?

  • 无运行时多态:模板是编译期处理的,不需要虚函数、基类指针这些运行时多态的元素
  • 无动态内存分配:Parent和MockMember都在栈上创建,完全避开了new/delete
  • 业务代码无侵入:默认模板参数是真实的Member,正常使用时依然可以写Parent parent;,不需要修改原有业务逻辑
  • 测试逻辑清晰:直接通过Mock验证方法调用,符合GTest/GMock的最佳实践

补充:如果无法修改Parent类?

如果你因为某些原因不能修改Parent的源代码,还有一个变通方案:使用依赖注入的变体,把Member作为Parent构造函数的参数传入,但用栈上对象而非指针:

// 修改后的Parent(如果允许的话)
class Parent {
private:
    Member& member_; // 引用而非指针,避免动态分配
public:
    // 传入栈上的Member对象引用
    explicit Parent(Member& member) : member_(member) {}

    void parent_method() {
        member_.member_method();
    }
};

// 测试时:
TEST(ParentTest, ParentMethodCallsMemberMethod) {
    MockMember mock_member; // 栈上Mock
    Parent parent(mock_member); // 传入引用

    EXPECT_CALL(mock_member, member_method()).Times(1);
    parent.parent_method();
}

不过这个方案需要修改Parent的构造函数,而模板方案的侵入性更小,更推荐前者。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:01:12