如何使用gmock mock指定大小的vector完成C++类方法单元测试?
问题根因
首先明确两个核心错误:
std::vector的size()方法不是虚函数,即使继承子类覆写该方法,也不存在运行时多态效果,父类指针/引用调用该方法永远会走原生std::vector的实现- 你把
MockVector对象传给接收std::vector<int>的构造函数时,会发生对象切片,子类的mock相关数据会被完全截断,Foo内部存储的就是原生std::vector对象,mock逻辑自然不会生效
你之前尝试改引用、传指针都没用,核心原因就是没有虚函数的前提下,父类类型的引用/指针永远不会调用子类覆写的方法。
可行的解决方案
推荐使用**编译期多态(模板)**实现mock,完全不需要修改Foo的对外契约,业务代码无侵入:
步骤1:修改Foo为模板类,设置默认模板参数
// 新增模板参数,默认值为std::vector<int>,原有业务代码无需任何修改 template <typename VectorType = std::vector<int>> class Foo { VectorType storedVector; public: explicit Foo(VectorType inputVector); bool isSizeGreaterThanInt(); }; template <typename VectorType> Foo<VectorType>::Foo(VectorType inputVector) : storedVector(std::move(inputVector)) { } template <typename VectorType> bool Foo<VectorType>::isSizeGreaterThanInt() { return storedVector.size() > INT32_MAX; }
修改后业务代码仍可以按原来的方式调用Foo<>(省略模板参数就会用默认的std::vector<int>),对外接口完全没有变化,不会修改原有契约。
步骤2:调整测试代码,传入MockVector作为模板参数
template <typename VectorValueType> class MockVector { public: // 不需要继承std::vector,只需要实现你用到的方法即可 MOCK_CONST_METHOD0_T(size, size_t()); // 如果Foo用到其他vector方法,在这里补充mock即可 }; TEST(FooTest, SizeGreaterThanInt32MaxReturnsTrue) { const size_t fakeLargeSize = static_cast<size_t>(INT32_MAX) + 1; MockVector<int> mockVector; // 可以加Times(1)验证size方法确实被调用了1次 EXPECT_CALL(mockVector, size()).WillOnce(testing::Return(fakeLargeSize)); // 传入MockVector作为模板参数,Foo内部存储的就是MockVector对象,不会切片 Foo<MockVector<int>> foo(std::move(mockVector)); ASSERT_TRUE(foo.isSizeGreaterThanInt()); }
这个方案还能直接验证isSizeGreaterThanInt确实调用了传入vector的size()方法,只需要调整EXPECT_CALL的Times参数即可,完全满足你的测试需求。
其他可选方案
如果完全不想修改Foo的代码,也可以使用编译器级别的打桩方案,比如GCC的--wrap参数 hook 掉std::vector<int>::size()的实现,但这种方案和编译器强绑定,兼容性差,远不如模板方案通用易维护。
内容的提问来源于stack exchange,提问作者Philip P.
相关产品推荐
相关产品推荐

