如何使用Google Test容器匹配器检查容器中的ValueObject?
问题原因
- 你的C++容器
std::vector<Character*>存储的是指针类型,Google Test默认匹配器会直接比较指针的内存地址,而非指针指向的对象内容。你通过std::make_unique创建的临时对象是新的内存地址,和容器中存储的指针地址必然不同,导致匹配失败。 - 即使你解引用临时对象(如
*std::make_unique<Character>(...)),此时匹配器是拿Character对象和容器中的Character*指针做比较,类型不匹配,Google Test无法正确调用你实现的==运算符来比较对象内容。
解决方案
1. 使用Pointee匹配器比较指针指向的对象内容
Google Test提供testing::Pointee匹配器,用于将对象匹配器包装后作用于指针类型的容器元素,会自动解引用指针并调用你实现的==运算符比较对象内容:
检查集合包含指定元素
std::vector<Character *> charactersList = finder.FindFamilyByLastName("Wheeler"); // 用Pointee包装对象匹配器,比较指针指向的内容 ASSERT_THAT(charactersList, testing::Contains(testing::Pointee(Character("Nancy", "Wheeler"))));
检查集合元素(严格顺序)
如果需要和C#的CollectionAssert.AreEqual一样严格检查顺序,使用ElementsAre配合Pointee:
ASSERT_THAT(charactersList, testing::ElementsAre( testing::Pointee(Character("Nancy", "Wheeler")), testing::Pointee(Character("Mike", "Wheeler")), testing::Pointee(Character("Karen", "Wheeler")) ));
检查集合元素(不关心顺序,对应C#的AreEquivalent)
如果不需要严格顺序,和C#的CollectionAssert.AreEquivalent行为一致,改用UnorderedElementsAre:
ASSERT_THAT(charactersList, testing::UnorderedElementsAre( testing::Pointee(Character("Nancy", "Wheeler")), testing::Pointee(Character("Mike", "Wheeler")), testing::Pointee(Character("Karen", "Wheeler")) ));
2. (可选)修改容器存储类型(更推荐)
如果业务允许,将容器从std::vector<Character*>改为存储值对象std::vector<Character>,或智能指针std::vector<std::unique_ptr<Character>>:
- 若存储值对象,可直接使用
Contains、ElementsAre等匹配器,无需Pointee,行为更接近C#的集合断言:std::vector<Character> charactersList = finder.FindFamilyByLastName("Wheeler"); ASSERT_THAT(charactersList, testing::Contains(Character("Nancy", "Wheeler"))); ASSERT_THAT(charactersList, testing::UnorderedElementsAre( Character("Nancy", "Wheeler"), Character("Mike", "Wheeler"), Character("Karen", "Wheeler") )); - 若使用智能指针
std::unique_ptr<Character>,Pointee匹配器依然适用,同时能避免手动管理内存的问题。
内容的提问来源于stack exchange,提问作者Emily Bache
相关产品推荐
相关产品推荐

