Google C++ Mocking Framework Cheat Sheet中文版
  
 ·                     定义一个模拟(Mock)类 
 ·                                模拟(Mocking)普通类 
 ·                                模拟(Mocking)模板类 
 ·                                为模拟函数(Mock Functions)指定调用约定 
 ·                     在测试中使用模拟 
 ·                     设置默认动作(Default Actions) 
 ·                     设置预期(Expectations) 
 ·                     匹配器(Matchers) 
 ·                                通配符 
 ·                                一般比较 
 ·                                浮点数匹配器 
 ·                                字符串匹配器 
 ·                                容器匹配器 
 ·                                成员匹配器 
 ·                                匹配函数或函数对象的返回值 
 ·                                指针匹配器 
 ·                                使用函数或函数对象作为匹配器 
 ·                                多参数匹配器 
 ·                                复合匹配器 
 ·                                转换匹配器 
 ·                                匹配器作为谓词(Predicates) 
 ·                                匹配器作为测试断言 
 ·                     动作(Actions) 
 ·                                返回一个值 
 ·                                副作用(Side Effects) 
 ·                                使用函数或函数对象作为动作(Action) 
 ·                                默认动作(Default Action) 
 ·                                复合动作(Composite Actions) 
 ·                     基数(Cardinalities) 
 ·                     序列(Sequences) 
 ·                     验证并重置Mock 
  
 定义一个模拟(Mock)类
  假设有
 class Foo { ...
 virtual ~Foo();
 virtual int GetSize() const = 0;
 virtual string Describe(const char* name) = 0;
 virtual string Describe(int type) = 0;
 virtual bool Process(Bar elem, int count) = 0;
};
(注意 ~Foo() 必须 是virtual的) 我们可以如下定义它的模拟类
 #include <gmock/gmock.h>
 
class MockFoo : public Foo { MOCK_CONST_METHOD0(GetSize, int());
 MOCK_METHOD1(Describe, string(const char* name));
 MOCK_METHOD1(Describe, string(int type));
 MOCK_METHOD2(Process, bool(Bar elem, int count));
};
如下,建立一个"合适"的模拟对象 (mock object)来忽略所有不关心的调用,或者是一个"精确"的模拟对象让这些调用置为失败:
NiceMock<MockFoo> nice_foo; // The type is a subclass of MockFoo.
StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
要模拟
 template <typename Elem>
class StackInterface { ...
 virtual ~StackInterface();
 virtual int GetSize() const = 0;
 virtual void Push(const Elem& x) = 0;
};
(注意 ~StackInterface() 必须 是 virtual 的) 只要追加_T 到 MOCK_* 宏即可:
 template <typename Elem>
class MockStack : public StackInterface<Elem> { ...
 MOCK_CONST_METHOD0_T(GetSize, int());
 MOCK_METHOD1_T(Push, void(const Elem& x));
};
如果你模拟的函数不是使用默认的调用约定,你可以追加 _WITH_CALLTYPE 到前两段讲到的所有宏里,并把调用约定作为宏的第一个参数,例如,
MOCK_METHOD_1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int n));
 MOCK_CONST_METHOD2_WITH_CALLTYPE(
      STDMETHODCALLTYPE, Bar, int(double x, double y));
这里的 STDMETHODCALLTYPE 是Windows中的头文件 <objbase.h> 定义的.
在测试中使用模拟(Mocking)
典型的流程是:
1.                引入你要用到的 Google Mock 名称. 除宏或其它特别提到的之外所有 Google Mock 名称都位于testing 名空间之下. 
2.                建立模拟对象(mock objects). 
3.                可选的,设置模拟对象的默认动作. 
4.                在模拟对象上设置你的预期(它们怎样被调用,应该怎样回应?). 
5.                调用使用模拟对象的代码,如有必要,使用Google Test断言检查返回值. 
6.                当模拟对象析构后,Google Mock 自动验证它是否达到所有预期. 
 
这里是一个例子:
1.                using testing::Return;  
2.                  
3.                TEST(BarTest, DoesThis) { 
4.                MockFoo foo;  
5.                  
6.                ON_CALL(foo, GetSize())  
7.                .WillByDefault(Return(1)); 
8.                  
9.                  
10.            EXPECT_CALL(foo, Describe(5))  
11.            .Times(3) 
12.            .WillRepeatedly(Return("Category 5")); 
13.              
14.              
15.            EXPECT_EQ("good", MyProductionFunction(&foo));  
16.            }  
设置默认动作
对于返回void, bool, 数值, 或指针的函数, Google Mock 都有一个内置默认动作.
要自定义返回类型为T的函数的默认动作:
1.                using testing::DefaultValue; 
2.                  
3.                DefaultValue<T>::Set(value);  
4.                 
5.                DefaultValue<T>::Clear();  
要自定义特定方法的默认动作,使用ON_CALL():
ON_CALL(mock_object, method(matchers))
 .WithArguments(multi_argument_matcher) ?
 .WillByDefault(action);
设置预期(Expectations)
EXPECT_CALL()在模拟方法(mock method)上设置预期(它们怎样被调用?应该怎样回应?):
EXPECT_CALL(mock_object, method(matchers))
 .WithArguments(multi_argument_matcher) ?
 .Times(cardinality) ?
 .InSequence(sequences) *
 .WillOnce(action) *
 .WillRepeatedly(action) ?
 .RetiresOnSaturation(); ?
如果没有Times(), 那么cardinality就依据其它参数做出假定:
·                     Times(1) 既没有WillOnce()也没有WillRepeatedly(); 
·                     Times(n) 有n个WillOnce()但没有WillRepeatedly(), 这里的n >= 1; 
·                     Times(AtLeast(n)) 有n个WillOnce()并且有一个WillRepeatedly(), 这里的n >= 0. 
没用EXPECT_CALL()的方法可以自由地调用任意次, 并以默认动作应对每次调用.
匹配器(matcher)
匹配器 (matcher)匹配单个参数(指函数参数). 内置的匹配器分成几种类型(下面的argument指函数参数):
| _ | argument& nbsp;可以是适当类型的任意值 | 
| A<type>() 或 An<type>() | argument& nbsp;可以是type类型的任意值 | 
| 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 | 
| NULL | argument 是 NULL. | 
| NotNull() | argument 是一个非null指针. | 
| Ref(variable) | argument 是一个variable的引用. | 
| TypedEq<type>(value) | argument 是type类型并且等于value.当模拟函数被重载时你可能需要用它来代替Eq(value). | 
除了Ref(), 这些匹配器在测试用例中使用一份value的拷贝来修改或析构. 如果编译器提示value没有public的拷贝构造, 可以尝试使用ByRef()包装, 比如. Eq(ByRef(non_copyable_value)). 如果你这样做的话, 请确保调用之后non_copyable_value没有被修改.
浮点数匹配器
| 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是相等的. | 
这些匹配器使用基于ULP的比较 (和Google Test所使用的一样). 它们基于预期的绝对值自动选择一个合理的误差范围. DoubleEq()和FloatEq()符合IEEE标准, 该标准要求比较两个NaN是否相等时返回false. NanSensitive* 版本则视两个NaN为相等, 这是用户通常所希望的.
argument可以是C风格字符串或C++的string对象:
| ContainsRegex(string) | argument 匹配给定的正则表达式. | 
| EndsWith(suffix) | argument 含有后缀suffix. | 
| HasSubstr(string) | argument 含有子串string. | 
| MatchesRegex(string) | argument 从第一个字符到最后一个字符都完全匹配给定的正则表达式. | 
| StartsWith(prefix) | argument 含有前缀prefix. | 
| StrCaseEq(string) | argument 与string相等, 忽略大小写. | 
| StrCaseNe(string) | argument 与string不等, 忽略大小写. | 
| StrEq(string) | argument 与string相等. | 
| StrNe(string) | argument 与string不等. | 
StrCaseEq(), StrCaseNe(), StrEq(), 和 StrNe() 也能工作于宽字符字符串.
很多STL-风格容器支持==, 所以你可以使用Eq(expected_container)或简单地expected_container来精确匹配容器. 如果你想直接写元素或更灵活地匹配, 可以使用:
| ElementsAre(e0, e1, ..., en) | argument 有n + 1个元素, 每i个元素匹配ei, 它们可以是一个值或是一个匹配器. 允许0到10个参数. | 
| ElementsAreArray(array) 或 ElementsAreArray(array, count) | 和ElementsAre()相同, 除了预期值/匹配器来源于一个C风格数组. | 
| Field(&class::field, m) | argument.field (或 argument->field, 当argument是一个指针时)与匹配器m匹配, 这里的argument是一个class类的实例. | 
| Property(&class::property, m) | argument.property() (或 argument->property(), 当argument是一个指针时)与匹配器m匹配, 这里的argument是一个class类的实例. | 
| ResultOf(f, m) | f(argument) 与匹配器m匹配, 这里的f是一个函数或函数对象. | 
| Pointee(m) | argument (不论是智能指针还是原始指针) 指向的值与匹配器m匹配. | 
| Truly(predicate) | predicate(argument) 返回值为true, 这里的predicate是一个函数或函数对象. | 
多参数匹配器
这些匹配器为元组类型(tuple types). 它们可以用在.WithArguments()里匹配两个参数的函数:
| Eq() | arg1 == arg2 | 
| Ge() | arg1 >= arg2 | 
| Gt() | arg1 > arg2 | 
| Le() | arg1 <= arg2 | 
| Lt() | arg1 < arg2 | 
| Ne() | arg1 != arg2 | 
复合匹配器
你可以把一个或多个匹配器合成一个匹配器:
| AllOf(m1, m2, ..., mn) | argument 匹配所有的匹配器m1到mn. | 
| AnyOf(m1, m2, ..., mn) | argument 至少匹配m1到mn中的一个. | 
| Not(m) | argument 不与匹配器m匹配. | 
| MatcherCast<T>(m) | 转换匹配器m为Matcher<T>类型. | 
通过Matches(m),Google Mock 能让你转换一个匹配器m到一个无参数谓词(就象STL算法使用的一样).
| ASSERT_THAT(expression, m) | 如果expression的值和匹配器m不匹配,就产生一个致命失败. | 
| EXPECT_THAT(expression, m) | 如果expression的值和匹配器m不匹配,就产生一个非致命失败. | 
动作(Actions)
动作 (Actions)指定了一个模拟函数被调用时应该做什么.
| Return() | 从一个void的模拟函数中返回 | 
| Return(value) | 返回value. | 
| ReturnNull() | 返回NULL指针. | 
| ReturnRef(variable) | 返回variable的引用. | 
| Assign(&variable, value) | 给variable 赋值value. | 
| SetArgumentPointee<N>(value) | 给第N(0-based)个参数指向的变量赋值value. | 
| SetArrayArgument<N>(first, last) | 拷贝源范围[first, last)里的元素到第N(0- based)个参数指向的数组, 它可以是一个指针或一个迭代器. 这个动作不会改变源范围元素的所有权. | 
| SetErrnoAndReturn(error, value) | 设置errno为error,并且返回value. | 
| Invoke(f) | 使用模拟函数的参数调用f, 这里的f可以是全局/静态函数或函数对象. | 
| Invoke(object_pointer, &class::method) | 使用模拟函数的参数调用object_pointer对象的mothod方法. | 
| InvokeWithoutArgs(f) | 无参数调用f, 这里的f可以是全局/静态函数或函数对象. | 
| InvokeWithoutArgs(object_pointer, &class::method) | 无参数调用object_pointer对象的mothod方法. | 
| InvokeArgument<N>(arg1, arg2, ..., argk) | 调用模拟函数的第N个(0-based)参数, 这个参数必须是一个函数或函数对象, 传入这里的k个参数. | 
这里调用函数的返回值将作为动作的返回值.
当定义一个函数或函数对象用于Invoke*(), 你可以使用Unused来声明一些不用的参数:
double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); } ...
 EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
在 InvokeArgument<N>(...), 如果一个参数需要引用传递, 可以使用ByRef()包装. 例如,
 InvokeArgument<2>(5, string("Hi"), ByRef(foo))
调用模拟函数的第二个参数, 以传值的方式传入5和string("Hi"), 引用的方式传入foo.
| DoDefault() | 使用默认动作(由ON_CALL()指定或内置). | 
注意: 由于技术原因, DoDefault()不能用于复合动作 - 尝试的结果是一个运行期错误.
| DoAll(a1, a2, ..., an) | 每次发动时执行a1到an的所有动作. | 
| IgnoreResult(a) | 执行动作a并忽略它的返回值. a不能返回void. | 
| WithArg<N>(a) | 传入模拟函数的第N个(0-based)参数作为动作a的参数并执行之. | 
| WithArgs<N1, N2, ..., Nk>(a) | 传入选中的模拟函数的多个第N个(0-based)参数作为动作a的参数并执行之. | 
| WithoutArgs(a) | 无参数执行动作a. | 
基数(Cardinalities)
基数用于Times()中来指定模拟函数将被调用多少次:
| AnyNumber() | 函数可以被调用任意次. | 
| AtLeast(n) | 预计至少调用n次. | 
| AtMost(n) | 预计至多调用n次. | 
| Between(m, n) | 预计调用次数在m和n(包括n)之间. | 
| Exactly(n) 或 n | 预计精确调用n次. 特别是, 当n为0时,函数应该永远不被调用. | 
序列(Sequences)
序列 (Sequences) 指定预期的顺序. 在同一序列里的所有预期调用必须按它们指定的顺序发生; 反之则可以是任意顺序.
建立序列:
 Sequence s1, s2;
使用序列:
EXPECT_CALL(foo, Reset())
 .InSequence(s1, s2)
 .WillOnce(Return(true));
EXPECT_CALL(foo, GetSize())
 .InSequence(s1)
 .WillOnce(Return(1));
EXPECT_CALL(foo, Describe(A<const char*>()))
 .InSequence(s2)
 .WillOnce(Return("dummy"));
(Reset()必须在GetSize()和Describe()之前被调用; 之后两个则可以任意顺序.)
方便地在一个序列中放入多个预期:
{ InSequence dummy;
 
 EXPECT_CALL(...)...;
 EXPECT_CALL(...)...;
 ...
 EXPECT_CALL(...)...;
}
(在dummy的生命周期内的所有预期的调用必须以精确的顺序发生. 至于名字dummy与此无关.)
验证并重置 Mock
当模板对象析构时Google Mock将验证其上的所有预期, 或者你也可以提前做这些事:
1.                using testing::Mock; 
2.                ... 
3.                 
4.                 
5.                Mock::VerifyAndClearExpectations(&mock_obj); 
6.                ... 
7.                 
8.                 
9.                 
10.            Mock::VerifyAndClear(&mock_obj);