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

如何使用GMock模拟返回类型为模板的成员函数?

如何模拟模板成员函数getVar()?
#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <memory>
#include <iostream>
#include <string>

using testing::_;
using testing::AllOf;
using testing::Args;
using testing::Return;

struct Base {
    Base() {
        std::cout << "Base constructed" << std::endl;
    }
};

struct Foo {
    template <typename T>
    T* getVar() {
        return new T; // 忽略内存泄漏,仅用于测试
    }
};

struct Bar {
    Bar(Foo& f) : f(f) {}

    virtual void testFoo() {
        f.getVar<Base>();
    }

    Foo f;
};

struct FooMock : public Foo {
    // 如何模拟getVar()?
};

struct TestBar : public Bar, public ::testing::Test {
    TestBar() : Bar(f) {}

    FooMock f;
};

TEST_F(TestBar, TestCase)
{
    testFoo();
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

如何模拟getVar()函数?该函数的返回类型为模板类型。我无法让MOCK_METHOD宏适配模板类型,也不知道如何将该函数纳入宏中使用。我希望完全避免为了模拟而重写getVar()函数。

补充说明:若采用高性能依赖注入方案,忽略原函数缺少virtual修饰的问题,该如何使用MOCK_METHOD模拟这个返回类型为模板的成员函数?


核心问题说明

C++不支持虚函数模板,而Google Mock的MOCK_METHOD宏依赖虚函数实现多态模拟,因此无法直接Mock模板成员函数。我们可以通过针对测试用到的模板实例手动桥接Mock函数,结合高性能依赖注入(模板参数注入)来实现需求。


解决方案1:针对特定模板实例桥接Mock函数

如果测试中仅用到getVar<Base>这类特定实例,可在FooMock中定义普通Mock函数,再通过模板特化将原模板函数桥接到Mock函数:

struct FooMock : public Foo {
    // 定义用于Mock的普通成员函数
    MOCK_METHOD(Base*, getVarBase, ());
};

// 在类外部特化getVar<Base>,桥接到Mock函数
template<>
Base* FooMock::getVar<Base>() {
    return getVarBase();
}

测试用例中设置期望:

TEST_F(TestBar, TestCase)
{
    EXPECT_CALL(f, getVarBase())
        .WillOnce(Return(new Base()));
    testFoo();
}

解决方案2:高性能依赖注入(无虚函数)

若要避免虚函数开销,可将Bar改为模板类,通过模板参数注入Foo或FooMock,结合上述桥接方式实现Mock:

  1. 修改Bar为模板类:
template<typename FooImpl>
struct Bar {
    Bar(FooImpl& f) : f(f) {}

    void testFoo() {
        f.getVar<Base>();
    }

    FooImpl& f;
};
  1. 调整测试类:
struct TestBar : public ::testing::Test {
    FooMock f;
    Bar<FooMock> bar{f};
};
  1. 测试用例中设置期望:
TEST_F(TestBar, TestCase)
{
    EXPECT_CALL(f, getVarBase())
        .WillOnce(Return(new Base()));
    bar.testFoo();
}

注意事项

  • 模板特化必须在命名空间级别(类外部)实现,不能在类内部直接特化模板成员函数。
  • 若需要Mock多个不同的模板实例(如getVar<int>、getVar<std::string>),只需为每个实例添加对应的Mock函数和特化即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 04:50:55