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) argumenttarget 之间的距离(由 abs(argument - target) 计算)匹配 m
DistanceFrom(target, get_distance, m) argumenttarget 之间的距离(由 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 的类型,IsTrueIsFalse 很有用。 在其他情况下,你可以使用基本的 EXPECT_TRUEEXPECT_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_doubledouble 值(绝对误差 <= max_abs_error),将两个 NaN 视为不相等。
FloatNear(a_float, max_abs_error) argument 是一个接近 a_floatfloat 值(绝对误差 <= max_abs_error),将两个 NaN 视为不相等。
NanSensitiveDoubleNear(a_double, max_abs_error) argument 是一个接近 a_doubledouble 值(绝对误差 <= max_abs_error),将两个 NaN 视为相等。
NanSensitiveFloatNear(a_float, max_abs_error) argument 是一个接近 a_floatfloat 值(绝对误差 <= 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,它可以是值或匹配器。与纯 ContainsEach 不同,这允许检查任意出现次数,包括使用 Contains(e).Times(0) 测试不存在的情况。
Each(e) argument 是一个容器,其中每个元素都与 e 匹配,它可以是值或匹配器。
ElementsAre(e0, e1, ..., en) argumentn + 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) argumentn + 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))

注意事项

成员匹配器

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 字段匹配 m1second 字段匹配 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(),因为获取函数的地址是脆弱的,并且通常不是函数契约的一部分。

注意事项

匹配函数、函数对象或回调的结果

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 m1mn 匹配。
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 m1mn 匹配。
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 mMatcher<T> 类型。
Truly(predicate) predicate(argument) 返回 C++ 认为为 true 的值,其中 predicate 是函数或函数对象。

AddressSatisfies(callback)Truly(callback) 获取 callback 的所有权,该 callback 必须是永久回调。

将 Matcher 用作谓词

Matcher 描述
Matches(m)(value) 如果 valuem 匹配,则计算结果为 true。 您可以将 Matches(m) 单独用作一元函数对象。
ExplainMatchResult(m, value, result_listener) 如果 valuem 匹配,则计算结果为 true,并将结果解释给 result_listener
Value(value, m) 如果 valuem 匹配,则计算结果为 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] 中的值。

注意事项

  1. MATCHER* 宏不能在函数或类内部使用。
  2. matcher 主体必须是纯函数(即,它不能有任何副作用,并且结果不能依赖于除被匹配的值和 matcher 参数之外的任何内容)。
  3. 您可以使用 PrintToString(x) 将任何类型的 x 值转换为字符串。
  4. 您可以在自定义 matcher 中使用 ExplainMatchResult() 来包装另一个 matcher,例如

    MATCHER_P(NestedPropertyMatches, matcher, "") {
      return ExplainMatchResult(matcher, arg.nested().property(), result_listener);
    }
    
  5. 您可以使用 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);
    }