如何在单元测试的MATCHER中访问Object类私有成员?
问题解答
1. 无需暴露公共方法访问私有成员的方案
可以通过友元机制配合条件编译,仅在测试环境下开放私有成员访问权限,避免污染生产代码:
方案一:给测试Matcher或测试类添加友元
在Object类中添加针对性的友元声明,仅让测试代码能访问私有成员:
template<typename T> class Object { // ... 原有成员 ... // 仅在测试编译模式下生效 #ifdef UNIT_TEST // 让Matcher函数直接访问私有成员 friend bool MatchMatcher_P2(const Object<T>& arg, const testing::Matcher<int>& m1, const testing::Matcher<int>& m2, testing::MatchResultListener* result_listener); // 或者直接让测试类成为友元 friend class UnitTest; #endif }; // 调整Matcher实现,直接访问私有成员 MATCHER_P2(Match, m1, m2, "") { return ExplainMatchResult(m1, arg.values.valueA, result_listener) && ExplainMatchResult(m2, arg.values.valueB, result_listener); }
注:UNIT_TEST是自定义编译宏,在编译测试代码时添加该宏定义即可。
方案二:编写测试专用的友元辅助函数
在Object类中封装一个仅测试可见的友元函数,用来获取内部状态结构:
template<typename T> class Object { // ... 原有成员 ... #ifdef UNIT_TEST friend const typename Object<T>::Values& GetObjectValues(const Object<T>& obj) { return obj.values; } #endif }; // Matcher中通过辅助函数间接访问内部成员 MATCHER_P2(Match, m1, m2, "") { const auto& values = GetObjectValues(arg); return ExplainMatchResult(m1, values.valueA, result_listener) && ExplainMatchResult(m2, values.valueB, result_listener); }
这种方式更封装,不会直接暴露单个成员,而是返回整个内部状态结构。
2. 将MATCHER_P2放入Object类内部的调用方式
Google Test的MATCHER_P2宏会展开生成嵌套的Matcher类,若放在Object类内部,需注意作用域和可见性:
实现示例
template<typename T> class Object { // ... 原有成员 ... public: // 将Matcher放在public作用域下,方便测试代码调用 MATCHER_P2(Match, m1, m2, "") { return ExplainMatchResult(m1, arg.values.valueA, result_listener) && ExplainMatchResult(m2, arg.values.valueB, result_listener); } };
调用方式
测试代码中需要通过Object<T>的作用域引用该Matcher,同时明确模板参数:
class UnitTest { TEST(UnitTest, testA) { Object<int> object; // 通过类作用域访问内部Matcher,指定模板参数 EXPECT_THAT(object, Object<int>::Match(Ne(0), Eq(0))); } };
注意事项
- 若将Matcher放在
private/protected作用域,需给测试类添加友元才能调用。 - Google Test的Matcher宏本身为全局/命名空间级设计,放在类内部可能引发作用域冲突或可读性问题,一般优先推荐友元方案。
内容的提问来源于stack exchange,提问作者xyf
相关产品推荐
相关产品推荐

