如何用C++ GMock匹配器测试unordered_map的键是否来自指定集合
嘿,这个场景我太熟悉了!GMock在“检查某个值是否属于指定集合”这块确实没有原生的匹配器,默认只提供了“集合包含某个值”的Contains,但其实我们可以用几种更优雅的方式解决,完全不用写那些嵌套的ResultOf和Value。
方案1:封装一个自定义匹配器(推荐)
这是最干净、可复用的方式,我们自己写一个IsInSet匹配器,专门用来检查值是否在目标集合里:
// 定义自定义匹配器,支持任意可查找的集合(比如unordered_set、set) MATCHER_P(IsInSet, expected_set, "") { return expected_set.find(arg) != expected_set.end(); }
然后使用的时候,先把expected_keys转成unordered_set(提升查找效率,尤其是集合比较大的时候),再配合Each和Key使用:
unordered_map<string, int> map{{"foo", 1}, {"bar", 2}, {"baz", 3}}; vector<string> expected_keys{"foo", "bar", "kaz"}; // 转成unordered_set加速查找 unordered_set<string> expected_set(expected_keys.begin(), expected_keys.end()); EXPECT_THAT(map, Each(Key(IsInSet(expected_set))));
如果你的expected_keys很小,也可以直接用vector配合std::find来写匹配器:
MATCHER_P(IsInVector, expected_vec, "") { return std::find(expected_vec.begin(), expected_vec.end(), arg) != expected_vec.end(); }
方案2:先提取map的键,再检查子集
如果不想自定义匹配器,也可以先把map的键提取到一个容器里,再用Each配合原生匹配器:
unordered_map<string, int> map{{"foo", 1}, {"bar", 2}, {"baz", 3}}; vector<string> expected_keys{"foo", "bar", "kaz"}; // 提取所有键到vector vector<string> actual_keys; std::transform(map.begin(), map.end(), std::back_inserter(actual_keys), [](const auto& pair) { return pair.first; }); // 检查每个实际键都在预期列表中 EXPECT_THAT(actual_keys, Each(Matches([&](const string& key) { return std::find(expected_keys.begin(), expected_keys.end(), key) != expected_keys.end(); })));
不过这种写法比自定义匹配器要啰嗦一些,复用性也差,适合临时用一下的场景。
关于你的思路
你的思路完全没问题!核心需求就是验证map的键集合是expected_keys的子集,GMock原生确实没有直接支持这种反向匹配的语法,但通过自定义匹配器或者小的代码转换就能完美解决,不用纠结自己的思路~
内容的提问来源于stack exchange,提问作者aruisdante
相关产品推荐
相关产品推荐

