Matchers 参考
一个 matcher 匹配一个单个参数。 你可以在 ON_CALL()
或 EXPECT_CALL()
中使用它,或者使用两个宏直接验证一个值
宏 | 描述 |
---|---|
EXPECT_THAT(actual_value, matcher) |
断言 actual_value 匹配 matcher 。 |
ASSERT_THAT(actual_value, matcher) |
与 EXPECT_THAT(actual_value, matcher) 相同,但它会生成一个致命错误。 |
警告: 支持通过 EXPECT_THAT(actual_value, expected_value)
进行相等匹配,但请注意,隐式转换可能会导致意外的结果。 例如,EXPECT_THAT(some_bool, "some string")
将会编译,并且可能会无意中通过。
最佳实践: 倾向于通过 EXPECT_THAT(actual_value, Eq(expected_value))
或 EXPECT_EQ(actual_value, expected_value)
显式地进行比较。
内置的 matchers (其中 argument
是函数参数, 例如上面的例子中的 actual_value
, 或者在 EXPECT_CALL(mock_object, method(matchers))
的上下文中, method
的参数) 分为几个类别。除非另有说明,否则所有 matchers 都定义在 ::testing
命名空间中。
通配符
Matcher | 描述 |
---|---|
_ |
argument 可以是正确类型的任何值。 |
A<type>() 或 An<type>() |
argument 可以是类型 type 的任何值。 |
通用比较
Matcher | 描述 |
---|---|
Eq(value) 或 value |
argument == value |
Ge(value) |
argument >= value |
Gt(value) |
argument > value |
Le(value) |
argument <= value |
Lt(value) |
argument < value |
Ne(value) |
argument != value |
IsFalse() |
argument 在布尔上下文中评估为 false 。 |
DistanceFrom(target, m) |
argument 和 target 之间的距离(由 abs(argument - target) 计算)匹配 m 。 |
DistanceFrom(target, get_distance, m) |
argument 和 target 之间的距离(由 get_distance(argument, target) 计算)匹配 m 。 |
IsTrue() |
argument 在布尔上下文中评估为 true 。 |
IsNull() |
argument 是一个 NULL 指针(原始或智能)。 |
NotNull() |
argument 是一个非空指针(原始或智能)。 |
Optional(m) |
argument 是一个 optional<> ,它包含一个匹配 m 的值。(对于测试 optional<> 是否已设置,检查是否与 nullopt 相等。如果内部类型没有 == ,你可能需要使用 Eq(nullopt) 。) |
VariantWith<T>(m) |
argument 是一个 variant<> ,它持有类型 T 的替代方案,其值匹配 m 。 |
Ref(variable) |
argument 是对 variable 的引用。 |
TypedEq<type>(value) |
argument 具有类型 type 并且等于 value 。当模拟函数重载时,你可能需要使用它来代替 Eq(value) 。 |
除了 Ref()
,这些 matchers 都会复制 value
,以防它稍后被修改或销毁。如果编译器抱怨 value
没有公共复制构造函数,请尝试将其包装在 std::ref()
中,例如 Eq(std::ref(non_copyable_value))
。 如果你这样做,请确保之后没有更改 non_copyable_value
,否则你的 matcher 的含义将会改变。
当你需要使用 matcher,或者对于可以显式转换为 Boolean,但不能隐式转换为 Boolean 的类型,IsTrue
和 IsFalse
很有用。 在其他情况下,你可以使用基本的 EXPECT_TRUE
和 EXPECT_FALSE
断言。
浮点 Matchers
Matcher | 描述 |
---|---|
DoubleEq(a_double) |
argument 是一个 double 值,近似等于 a_double ,将两个 NaN 视为不相等。 |
FloatEq(a_float) |
argument 是一个 float 值,近似等于 a_float ,将两个 NaN 视为不相等。 |
NanSensitiveDoubleEq(a_double) |
argument 是一个 double 值,近似等于 a_double ,将两个 NaN 视为相等。 |
NanSensitiveFloatEq(a_float) |
argument 是一个 float 值,近似等于 a_float ,将两个 NaN 视为相等。 |
IsNan() |
argument 是任何具有 NaN 值的浮点类型。 |
上面的 matchers 使用基于 ULP 的比较(与 googletest 中使用的相同)。 它们会根据期望值的绝对值自动选择合理的误差范围。DoubleEq()
和 FloatEq()
符合 IEEE 标准,该标准要求比较两个 NaN 的相等性以返回 false。 NanSensitive*
版本将两个 NaN 视为相等,这通常是用户想要的。
Matcher | 描述 |
---|---|
DoubleNear(a_double, max_abs_error) |
argument 是一个接近 a_double 的 double 值(绝对误差 <= max_abs_error ),将两个 NaN 视为不相等。 |
FloatNear(a_float, max_abs_error) |
argument 是一个接近 a_float 的 float 值(绝对误差 <= max_abs_error ),将两个 NaN 视为不相等。 |
NanSensitiveDoubleNear(a_double, max_abs_error) |
argument 是一个接近 a_double 的 double 值(绝对误差 <= max_abs_error ),将两个 NaN 视为相等。 |
NanSensitiveFloatNear(a_float, max_abs_error) |
argument 是一个接近 a_float 的 float 值(绝对误差 <= max_abs_error ),将两个 NaN 视为相等。 |
字符串 Matchers
argument
可以是 C 字符串或 C++ 字符串对象
Matcher | 描述 |
---|---|
ContainsRegex(string) |
argument 匹配给定的正则表达式。 |
EndsWith(suffix) |
argument 以字符串 suffix 结尾。 |
HasSubstr(string) |
argument 包含 string 作为子字符串。 |
IsEmpty() |
argument 是一个空字符串。 |
MatchesRegex(string) |
argument 匹配给定的正则表达式,匹配从第一个字符开始,到最后一个字符结束。 |
StartsWith(prefix) |
argument 以字符串 prefix 开头。 |
StrCaseEq(string) |
argument 等于 string ,忽略大小写。 |
StrCaseNe(string) |
argument 不等于 string ,忽略大小写。 |
StrEq(string) |
argument 等于 string 。 |
StrNe(string) |
argument 不等于 string 。 |
WhenBase64Unescaped(m) |
argument 是一个 base-64 转义的字符串,其未转义的字符串匹配 m 。支持来自 RFC 4648 的 web 安全格式。 |
ContainsRegex()
和 MatchesRegex()
获取 RE
对象的所有权。它们使用此处定义的正则表达式语法。除了 ContainsRegex()
和 MatchesRegex()
之外,所有这些匹配器也适用于宽字符串。
容器匹配器
大多数 STL 风格的容器都支持 ==
,因此你可以使用 Eq(expected_container)
或直接使用 expected_container
来精确匹配容器。如果你想内联编写元素,更灵活地匹配它们,或者获得更丰富的信息,你可以使用
Matcher | 描述 |
---|---|
BeginEndDistanceIs(m) |
argument 是一个容器,其 begin() 和 end() 迭代器之间由匹配 m 的增量数分隔。例如,BeginEndDistanceIs(2) 或 BeginEndDistanceIs(Lt(2)) 。对于定义 size() 方法的容器,SizeIs(m) 可能更有效。 |
ContainerEq(container) |
与 Eq(container) 相同,但失败消息还包括哪些元素在一个容器中而不是另一个容器中。 |
Contains(e) |
argument 包含一个与 e 匹配的元素,它可以是值或匹配器。 |
Contains(e).Times(n) |
argument 包含与 e 匹配的元素,它可以是值或匹配器,并且匹配的数量是 n ,它可以是值或匹配器。与纯 Contains 和 Each 不同,这允许检查任意出现次数,包括使用 Contains(e).Times(0) 测试不存在的情况。 |
Each(e) |
argument 是一个容器,其中每个元素都与 e 匹配,它可以是值或匹配器。 |
ElementsAre(e0, e1, ..., en) |
argument 有 n + 1 个元素,其中第 *i* 个元素匹配 ei ,它可以是值或匹配器。 |
ElementsAreArray({e0, e1, ..., en}) , ElementsAreArray(a_container) , ElementsAreArray(begin, end) , ElementsAreArray(array) , 或 ElementsAreArray(array, count) |
与 ElementsAre() 相同,不同之处在于预期的元素值/匹配器来自初始化列表、STL 风格的容器、迭代器范围或 C 风格的数组。 |
IsEmpty() |
argument 是一个空容器 (container.empty() )。 |
IsSubsetOf({e0, e1, ..., en}) , IsSubsetOf(a_container) , IsSubsetOf(begin, end) , IsSubsetOf(array) , 或 IsSubsetOf(array, count) |
argument 匹配 UnorderedElementsAre(x0, x1, ..., xk) ,对于预期匹配器的某个子集 {x0, x1, ..., xk} 。 |
IsSupersetOf({e0, e1, ..., en}) , IsSupersetOf(a_container) , IsSupersetOf(begin, end) , IsSupersetOf(array) , 或 IsSupersetOf(array, count) |
argument 的某个子集匹配 UnorderedElementsAre( 预期匹配器 ) 。 |
Pointwise(m, container) , Pointwise(m, {e0, e1, ..., en}) |
argument 包含与 container 中相同数量的元素,并且对于所有 i,(argument 中的第 i 个元素,container 中的第 i 个元素) 匹配 m ,这是一个关于 2 元组的匹配器。例如,Pointwise(Le(), upper_bounds) 验证 argument 中的每个元素都不超过 upper_bounds 中的相应元素。请参见下面的更多详细信息。 |
SizeIs(m) |
argument 是一个容器,其大小匹配 m 。例如,SizeIs(2) 或 SizeIs(Lt(2)) 。 |
UnorderedElementsAre(e0, e1, ..., en) |
argument 有 n + 1 个元素,并且在元素的某些排列下,每个元素都与 ei 匹配(对于不同的 i ),它可以是一个值或一个匹配器。 |
UnorderedElementsAreArray({e0, e1, ..., en}) , UnorderedElementsAreArray(a_container) , UnorderedElementsAreArray(begin, end) , UnorderedElementsAreArray(array) , 或 UnorderedElementsAreArray(array, count) |
与 UnorderedElementsAre() 相同,不同之处在于预期的元素值/匹配器来自初始化列表、STL 风格的容器、迭代器范围或 C 风格的数组。 |
UnorderedPointwise(m, container) , UnorderedPointwise(m, {e0, e1, ..., en}) |
与 Pointwise(m, container) 类似,但忽略元素的顺序。 |
WhenSorted(m) |
当使用 < 运算符对 argument 进行排序时,它与容器匹配器 m 匹配。例如,WhenSorted(ElementsAre(1, 2, 3)) 验证 argument 包含元素 1、2 和 3,忽略顺序。 |
WhenSortedBy(comparator, m) |
与 WhenSorted(m) 相同,不同之处在于使用给定的比较器而不是 < 对 argument 进行排序。例如,WhenSortedBy(std::greater(), ElementsAre(3, 2, 1)) 。 |
注意事项
- 这些匹配器也可以匹配
- 通过引用传递的本机数组(例如,在
Foo(const int (&a)[5])
中),以及 - 作为指针和计数传递的数组(例如,在
Bar(const T* buffer, int len)
中 - 请参见 多参数匹配器)。
- 通过引用传递的本机数组(例如,在
- 要匹配的数组可以是多维的(即,其元素可以是数组)。
-
Pointwise(m, ...)
和UnorderedPointwise(m, ...)
中的m
应该是::std::tuple<T, U>
的匹配器,其中T
和U
分别是实际容器和预期容器的元素类型。例如,要比较两个Foo
容器,其中Foo
不支持operator==
,可以编写MATCHER(FooEq, "") { return std::get<0>(arg).Equals(std::get<1>(arg)); } ... EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos));
成员匹配器
Matcher | 描述 |
---|---|
Field(&class::field, m) |
argument.field (或者当 argument 是普通指针时,argument->field )匹配匹配器 m ,其中 argument 是类型为*class*的对象。 |
Field(field_name, &class::field, m) |
与双参数版本相同,但提供更好的错误消息。 |
Key(e) |
argument.first 匹配 e ,它可以是值或匹配器。例如,Contains(Key(Le(5))) 可以验证 map 是否包含键 <= 5 。 |
Pair(m1, m2) |
argument 是一个 std::pair ,其 first 字段匹配 m1 ,second 字段匹配 m2 。 |
FieldsAre(m...) |
argument 是一个兼容的对象,其中每个字段都与匹配器 m... 逐片匹配。兼容的对象是指任何支持 std::tuple_size<Obj> + get<I>(obj) 协议的对象。在 C++17 及更高版本中,这也支持与结构化绑定兼容的类型,例如聚合。 |
Property(&class::property, m) |
argument.property() (或者当 argument 是普通指针时,argument->property() )匹配匹配器 m ,其中 argument 是类型为*class*的对象。方法 property() 必须不接受任何参数,并且声明为 const 。 |
Property(property_name, &class::property, m) |
与双参数版本相同,但提供更好的错误消息。 |
警告:不要对你不拥有的成员函数使用 Property()
,因为获取函数的地址是脆弱的,并且通常不是函数契约的一部分。
注意事项
-
你可以使用
FieldsAre()
来匹配任何支持结构化绑定的类型,例如std::tuple
、std::pair
、std::array
和聚合类型。例如std::tuple<int, std::string> my_tuple{7, "hello world"}; EXPECT_THAT(my_tuple, FieldsAre(Ge(0), HasSubstr("hello"))); struct MyStruct { int value = 42; std::string greeting = "aloha"; }; MyStruct s; EXPECT_THAT(s, FieldsAre(42, "aloha"));
匹配函数、函数对象或回调的结果
Matcher | 描述 |
---|---|
ResultOf(f, m) |
f(argument) 匹配匹配器 m ,其中 f 是函数或函数对象。 |
ResultOf(result_description, f, m) |
与双参数版本相同,但提供更好的错误消息。 |
指针匹配器
Matcher | 描述 |
---|---|
Address(m) |
std::addressof(argument) 的结果与 m 匹配。 |
Pointee(m) |
argument (可以是智能指针或原始指针) 指向的值与 matcher m 匹配。 |
Pointer(m) |
argument (可以是智能指针或原始指针) 包含一个与 m 匹配的指针。 m 将针对原始指针进行匹配,而不管 argument 的类型如何。 |
WhenDynamicCastTo<T>(m) |
当 argument 传递给 dynamic_cast<T>() 时,它与 matcher m 匹配。 |
多参数 Matcher
从技术上讲,所有 matcher 都匹配一个单个值。 “多参数” matcher 只是匹配一个元组的 matcher。 以下 matcher 可用于匹配元组 (x, y)
Matcher | 描述 |
---|---|
Eq() |
x == y |
Ge() |
x >= y |
Gt() |
x > y |
Le() |
x <= y |
Lt() |
x < y |
Ne() |
x != y |
您可以使用以下选择器来选择参数的子集(或重新排序),以参与匹配
Matcher | 描述 |
---|---|
AllArgs(m) |
等效于 m 。 在 .With(AllArgs(m)) 中用作语法糖很有用。 |
Args<N1, N2, ..., Nk>(m) |
使用基于 0 的索引选择的 k 个参数的元组与 m 匹配,例如 Args<1, 2>(Eq()) 。 |
复合 Matcher
您可以从一个或多个其他 matcher 创建 matcher
Matcher | 描述 |
---|---|
AllOf(m1, m2, ..., mn) |
argument 与所有 matcher m1 到 mn 匹配。 |
AllOfArray({m0, m1, ..., mn}) , AllOfArray(a_container) , AllOfArray(begin, end) , AllOfArray(array) , 或 AllOfArray(array, count) |
与 AllOf() 相同,除了 matcher 来自初始化列表、STL 风格的容器、迭代器范围或 C 风格的数组。 |
AnyOf(m1, m2, ..., mn) |
argument 与至少一个 matcher m1 到 mn 匹配。 |
AnyOfArray({m0, m1, ..., mn}) , AnyOfArray(a_container) , AnyOfArray(begin, end) , AnyOfArray(array) , 或 AnyOfArray(array, count) |
与 AnyOf() 相同,除了 matcher 来自初始化列表、STL 风格的容器、迭代器范围或 C 风格的数组。 |
Not(m) |
argument 与 matcher m 不匹配。 |
Conditional(cond, m1, m2) |
如果 cond 的计算结果为 true,则与 matcher m1 匹配,否则与 m2 匹配。 |
Matcher 的适配器
Matcher | 描述 |
---|---|
MatcherCast<T>(m) |
将 matcher m 强制转换为 Matcher<T> 类型。 |
SafeMatcherCast<T>(m) |
安全地强制转换 matcher m 到 Matcher<T> 类型。 |
Truly(predicate) |
predicate(argument) 返回 C++ 认为为 true 的值,其中 predicate 是函数或函数对象。 |
AddressSatisfies(callback)
和 Truly(callback)
获取 callback
的所有权,该 callback
必须是永久回调。
将 Matcher 用作谓词
Matcher | 描述 |
---|---|
Matches(m)(value) |
如果 value 与 m 匹配,则计算结果为 true 。 您可以将 Matches(m) 单独用作一元函数对象。 |
ExplainMatchResult(m, value, result_listener) |
如果 value 与 m 匹配,则计算结果为 true ,并将结果解释给 result_listener 。 |
Value(value, m) |
如果 value 与 m 匹配,则计算结果为 true 。 |
定义 Matcher
宏 | 描述 |
---|---|
MATCHER(IsEven, "") { return (arg % 2) == 0; } |
定义 matcher IsEven() 以匹配偶数。 |
MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "余数为 " << (arg % n); return (arg % n) == 0; } |
定义 matcher IsDivisibleBy(n) 以匹配可被 n 整除的数字。 |
MATCHER_P2(IsBetween, a, b, absl::StrCat(negation ? "不是" : "是", "在 ", PrintToString(a), " 和 ", PrintToString(b), " 之间")) { return a <= arg && arg <= b; } |
定义 matcher IsBetween(a, b) 以匹配范围 [a , b ] 中的值。 |
注意事项
MATCHER*
宏不能在函数或类内部使用。- matcher 主体必须是纯函数(即,它不能有任何副作用,并且结果不能依赖于除被匹配的值和 matcher 参数之外的任何内容)。
- 您可以使用
PrintToString(x)
将任何类型的x
值转换为字符串。 -
您可以在自定义 matcher 中使用
ExplainMatchResult()
来包装另一个 matcher,例如MATCHER_P(NestedPropertyMatches, matcher, "") { return ExplainMatchResult(matcher, arg.nested().property(), result_listener); }
-
您可以使用
DescribeMatcher<>
来描述另一个 matcher。 例如MATCHER_P(XAndYThat, matcher, "X that " + DescribeMatcher<int>(matcher, negation) + (negation ? " or" : " and") + " Y that " + DescribeMatcher<double>(matcher, negation)) { return ExplainMatchResult(matcher, arg.x(), result_listener) && ExplainMatchResult(matcher, arg.y(), result_listener); }