Google C++ Mocking Framework チートシート
以下のようなクラスが与えられた場合を考えます.
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));
};
不要な呼び出しを無視する「nice」モックオブジェクト,または,それらを失敗として扱う「strict」モックオブジェクト,を作るには次のようにします:
NiceMock<MockFoo> nice_foo; // MockFoo の派生クラス型
StrictMock<MockFoo> strict_foo; // MockFoo の派生クラス型
次のクラステンプレートをモック化するには
template <typename Elem>
class StackInterface {
public:
...
virtual ~StackInterface();
virtual int GetSize() const = 0;
virtual void Push(const Elem& x) = 0;
};
(~StackInterface() は必ず virtual であることに注意してください)MOCK_* マクロに _T を追加するだけです:
template <typename Elem>
class MockStack : public StackInterface<Elem> {
public:
...
MOCK_CONST_METHOD0_T(GetSize, int());
MOCK_METHOD1_T(Push, void(const Elem& x));
};
あなたのモック関数がデフォルトの呼び出し規約を利用しない場合,それを指定することができます.それには,前述の2つのセクションで説明したマクロすべてに _WITH_CALLTYPE を追加して,マクロの1番目の引数として呼び出し規約を与えます.次に例を示します.
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> で定義されています.
典型的な利用の流れは次のようになります:
以下に例を示します:
using ::testing::Return; // #1
TEST(BarTest, DoesThis) {
MockFoo foo; // #2
ON_CALL(foo, GetSize()) // #3
.WillByDefault(Return(1));
// ... その他のデフォルト Action ...
EXPECT_CALL(foo, Describe(5)) // #4
.Times(3)
.WillRepeatedly(Return("Category 5"));
// ... その他の Expectation ...
EXPECT_EQ("good", MyProductionFunction(&foo)); // #5
} // #6
void,bool,数値,ポインタを返す関数に対しては,Google Mock 組み込みのデフォルト Action があります.
戻り値型 T の関数のデフォルト Action を全体的にカスタマイズするには,次のようにします:
using ::testing::DefaultValue;
DefaultValue<T>::Set(value); // 返されるデフォルト値を設定します.
// ... モックを利用します ...
DefaultValue<T>::Clear(); // デフォルト値をリセットします.
特定のメソッドのデフォルト Action をカスタマイズするには,ON_CALL() を利用します:
ON_CALL(mock_object, method(matchers))
.With(multi_argument_matcher) ?
.WillByDefault(action);
EXPECT_CALL() は,モックメソッドに Expectation を設定します(どのように呼び出されるか?何をするのか?)
EXPECT_CALL(mock_object, method(matchers))
.With(multi_argument_matcher) ?
.Times(cardinality) ?
.InSequence(sequences) *
.After(expectations) *
.WillOnce(action) *
.WillRepeatedly(action) ?
.RetiresOnSaturation(); ?
Times() が省略された場合,cardinality は次のように仮定されます:
EXPECT_CALL() がないメソッドは,何度でも自由に呼び出され,そのたびにデフォルトアクションが実行されます.
matcher は,単一の引数にマッチします.これは,ON_CALL() または EXPECT_CALL() 内で利用したり,また値を直接検証するために利用することができます..
EXPECT_THAT(value, matcher) | value が matcher にマッチすることをアサートします. |
ASSERT_THAT(value, matcher) | 致命的な失敗を生成することを除いて,EXPECT_THAT(value, matcher) と同じです. |
組み込みの matcher (argument は関数の引数)は,いくつかのカテゴリに分類されます.
_ | argument は,正しい型の任意の値をとれます. |
A<type>() or An<type>() | argument は,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 |
IsNull() | argument は NULL ポインタ(生ポインタ,またはスマートポインタ). |
NotNull() | argument は NULL ポインタではない(生ポインタ,またはスマートポインタ). |
Ref(variable) | argument は variable の参照. |
TypedEq<type>(value) | argument の type 型で,value に等しい.モック関数がオーバーロードされた場合,Eq(value) の代わりにこれを使う必要があるかもしれません. |
Ref() を除いて,これらの matcher は,後から変更したり破棄したりするのに備えて value のコピーを作ります.コンパイラが value が public なコピーコンストラクタを持っていないというエラーを出した場合,例えば,Eq(ByRef(non_copyable_value)) というように ByRef() でラップしてみてくださいこれを使う場合,non_copyable_value を後から変更したり,あなたの定義した matcher の意味を変更したり,決してしないようにしてください.
DoubleEq(a_double) | argument は,a_double とおよそ等しい double 型の値.2つの NaN は等しくないとされます. |
FloatEq(a_float) | argument は,a_float とおよそ等しい float 型の値.2つの NaN は等しくないとされます. |
NanSensitiveDoubleEq(a_double) | argument は,a_double とおよそ等しい double 型の値.2つの NaN は等しいとされます. |
NanSensitiveFloatEq(a_float) | argument は,a_float とおよそ等しい float 型の値.2つの NaN は等しいとされます. |
これらの matcher は,(Google Test で利用されているものと同様に)ULP に基づいた比較を行います.ここでは,期待する値の絶対値に基づいた適切な誤差範囲が自動的に利用されます.DoubleEq() と FloatEq() は IEEE 標準に従い,NaN 同士の等価性を評価した場合に false を返します.NanSensitive* バージョンは,2つの 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 を使えば,正確にコンテナにマッチすることができます.しかし,要素をインラインで書きたい,より柔軟にマッチさせたい,メッセージを充実させたい,など場合は,以下を利用できます:
Contains(e) | argument は,e (値または matcher)にマッチする要素を含みます. |
Each(e) | argument は,すべての要素が e (値または matcher)にマッチするコンテナです. |
ElementsAre(e0, e1, ..., en) | argument は,n + 1 個の要素を持ち,i-番目の要素は ei (値または matcher)にマッチします.0 から 10 までの引数をとれます. |
ElementsAreArray(array) または ElementsAreArray(array, count) | 期待する要素の値/matcher がC形式の配列で表現されることを除いて,ElementsAre() と同じです. |
ContainerEq(container) | 失敗メッセージにも片方のコンテナだけに存在する要素が表示される点を除いて,Eq(container) と同じです. |
Pointwise(m, container) | argument は,container と同数の要素を持ち,全ての i に対して(argument の i-番目の要素,container の i-番目の要素が)m にマッチします.ここで m は,2要素タプル形式の matcher です.例えば Pointwise(Le(), upper_bounds) は,argument の各要素が,対応する upper_bounds の要素を超えないかどうかを検証します. |
これらの matcher は,次のようなものにもマッチします:
ここで,配列は多次元配列(例えば,要素が配列)でも構いません.
Field(&class::field, m) | argument.field(argument がただのポインタの場合は argument->field )は,matcher m にマッチします.ここで,argument は class 型のオブジェクトです. |
Key(e) | argument.first は,e (値または matcher)にマッチします.例えば,Contains(Key(Le(5))) は,マップに key <=5 が含まれていることを検証します. |
Pair(m1, m2) | argument は,1番目のフィールドが m1 に, 2番目のフィールドが m2 にマッチする std::pair です. |
Property(&class::property, m) | argument.property() (argument がただのポインタの場合は argument->property() )は,matcer m にマッチします.ここで,argument は class 型のオブジェクトです. |
ResultOf(f, m) | f(argument) は,matcher にマッチします.ここで f は関数またはファンクタです. |
Pointee(m) | argument (スマートポンタ,または生ポインタ)が指し示す値は,matcher m にマッチします. |
理論的には,すべての matcher は単一の値にマッチします.「複数の引数をとる」 matcher は,単にタプルにマッチする matcher です.以下の matcher は,タプル (x, y) にマッチさせるために利用できます:
Eq() | x == y |
Ge() | x >= y |
Gt() | x > y |
Le() | x <= y |
Lt() | x < y |
Ne() | x != y |
以下のセレクタを利用すると,引数の一部を抜き出し(または,順番を入れ替え)て,マッチングさせることができます
AllArgs(m) | m と等価です..With(AllArgs(m)) のシンタックスシュガーとして役立ちます. |
Args<N1, N2, ..., Nk>(m) | (0基準のインデックスによって) k 要素のタプルが引数から選択され,それが m にマッチします.例えば, Args<1, 2>(Eq()). |
1つまたは複数の matcher から, 新たに別の matcher を作ることができます.
AllOf(m1, m2, ..., mn) | argument は,m1 から mn までの全ての matcher にマッチします. |
AnyOf(m1, m2, ..., mn) | argument は,m1 から mn までの matcher のうち,少なくとも1つにマッチします. |
Not(m) | argument は,matcher m にマッチしません. |
MatcherCast<T>(m) | matcher m を,型 Matcher<T> にキャストします. |
SafeMatcherCast<T>(m) | matcher m を,型 Matcher<T> に安全にキャストします. |
Truly(predicate) | predicate(argument) は,C++ で true と判断されるなにかを返します.predicate は,関数またはファンクタです. |
Matches(m) | argument が m にマッチする場合に true を返す,1変数関数です. |
ExplainMatchResult(m, value, result_listener) | value が m にマッチする場合に true を返し,その結果を result_listener に説明します. |
Value(x, m) | x の値が m にマッチする場合に true を返します. |
MATCHER(IsEven, “”) { return (arg % 2) == 0; } | 偶数にマッチする matcher IsEven() を定義します. |
MATCHER_P(IsDivisibleBy, n, “”) { *result_listener << “where the remainder is ” << (arg % n); return (arg % n) == 0; } | n の倍数にマッチする matcher IsDivisibleBy(n) を定義します. |
MATCHER_P2(IsBetween, a, b, std::string(negation ? “isn’t” : “is”) + ” between ” + PrintToString(a) + ” and ” + PrintToString(b)) { return a <= arg && arg <= b; } | [a, b] の範囲内の値にマッチする matcher IsBetween(a, b) を定義します. |
注意:
ASSERT_THAT(expression, m) | expression の値が matcher m にマッチしなかった場合に,致命的な失敗を生成します. |
EXPECT_THAT(expression, m) | expression の値が matcher m にマッチしなかった場合に,致命的ではない失敗を生成します. |
Action は,モック関数が呼ばれたときに何をするのかを規定します.
Return() | void モック関数から返ります. |
Return(value) | value を返します.value の型がモック関数の戻り値型と異なる場合,value の型が変換されます.これは,Action 実行時ではなく,Expectation が設定されるときに行われます. |
ReturnArg<N>() | N-番目(0基準)の argument を返します. |
ReturnNew<T>(a1, ..., ak) | new T(a1, ..., ak); を返します.毎回異なるオブジェクトが作成されます. |
ReturnNull() | Null ポインタを返します. |
ReturnPointee(ptr) | ptr で指定される値を返します. |
ReturnRef(variable) | variable の参照を返します. |
ReturnRefOfCopy(value) | value のコピーの参照を返します.このコピーは,Action 時にのみ有効です. |
Assign(&variable, value) | value を variable に代入します. |
DeleteArg<N>() | N-番目(0基準)の argument を削除します.これはポインタである必要があります. |
SaveArg<N>(pointer) | N-番目(0基準)の argument を *pointer に保存します. |
SaveArgPointee<N>(pointer) | N-番目(0基準)の argument によって指される値を *pointer に保存します. |
SetArgReferee<N>(value) | N-番目(0基準)の argument によって参照される変数に,value を代入します. |
SetArgPointee<N>(value) | N-番目(0基準)の argument によって指される変数に,value を代入します. |
SetArgumentPointee<N>(value) | SetArgPointee<N>(value) と同じです.非推奨.v1.7.0 で廃止予定です. |
SetArrayArgument<N>(first, last) | 入力範囲 [first, last) の要素を,N-番目(0基準)の argument (これは,ポインタまたはイテレータ)によって指される配列にコピーします.Action は,入力範囲内の要素の所有権を持ちません. |
SetErrnoAndReturn(error, value) | error にエラー番号を設定して,value を返します. |
Throw(exception) | 与えられた exception を投げます.これは任意のコピー可能な値です.v1.1.0 以降で利用できます. |
Invoke(f) | モック関数に渡された argument を与えて f を呼び出します.ここで f は,グローバルで static な関数またはファンクタです. |
Invoke(object_pointer, &class::method) | モック関数に渡された argument を与えてオブジェクトの method を呼び出します. |
InvokeWithoutArgs(f) | f を呼び出します.ここで f は,グローバルで static な関数またはファンクタです.また,f は引数をとってはいけません. |
InvokeWithoutArgs(object_pointer, &class::method) | オブジェクトの,引数を取らない method を呼び出します |
InvokeArgument<N>(arg1, arg2, ..., argk) | モック関数のN-番目(0基準)の argument を呼び出します.これは k この引数をとる,関数またはファンクタである必要があります. |
呼び出された関数の戻り値は,Action の戻り値として利用されます.
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))
モック関数の2番目の argument に,5 と string(“Hi”) が値渡しされ,foo が参照渡しされます.
DoDefault() | (ON_CALL() によって指定される,または組み込みの)デフォルト Action を実行します. |
注意: 技術的な理由により,DoDefault() は複合 Action 内部では利用できません.利用しようとすると,ランタイムエラーが発生します.
DoAll(a1, a2, ..., an) | a1 から an までの Action が全て実行され,an の結果が毎回返されます.最初の n-1 個の Sub-Action は void を返すものでなければいけません. |
IgnoreResult(a) | Action a を実行し,その結果を無視します.a は,void を返してはいけません. |
WithArg<N>(a) | モック関数の N-番目(0基準)の argument を Action に渡し,それを実行します. |
WithArgs<N1, N2, ..., Nk>(a) | モック関数の引数を(0基準のインデックスで)選択し,Action a に渡して実行します. |
WithoutArgs(a) | 引数なしで Action a を実行します |
ACTION(Sum) { return arg0 + arg1; } | モック関数の 0番目と 1番目の argument の合計を返す Action Sum() を定義します. |
ACTION_P(Plus, n) { return arg0 + n; } | モック関数の 0番目の argument と n との和を返す Action Plus(n) を定義します. |
ACTION_Pk(Foo, p1, ..., pk) { statements; } | 与えられた statements を実行する,パラメータ化された Action Foo(p1, ..., pk) を定義します. |
ACTION* マクロは,関数またはマクロの中では利用できません.
これらは, Times() 内で,モック関数が呼び出される回数を指定するために利用されます:
AnyNumber() | 関数は何度でも呼び出すことができます. |
AtLeast(n) | 呼び出し回数は,最低でも n 回であることが期待されます. |
AtMost(n) | 呼び出し回数は,最高でも n 回であることが期待されます. |
Between(m, n) | 呼びだし回数は,m 回から n 回(これを含む)であることが期待されます. |
Exactly(n) or n | 呼び出しは,正確に n 回であることが期待されます.特に,n が 0 の場合は,呼び出しは起こりません. |
デフォルトでは,Expectation は任意の順序でマッチすることができます.いくつかの,またはすべての Expectaion を指定した順序通りにマッチする必要がある場合,それを行う方法は2つあります.これらの方法は,独立にも一緒にも利用できます.
using ::testing::Expectation;
...
Expectation init_x = EXPECT_CALL(foo, InitX());
Expectation init_y = EXPECT_CALL(foo, InitY());
EXPECT_CALL(foo, Bar())
.After(init_x, init_y);
これは,InitX() および InitY() が呼び出された後でのみ,Bar() を呼び出すことができる,ということを意味します.
Expectation を書くときにはまだ,事前に必要な処理の回数が不明な場合, ExpectationSet を利用して,それを数えることができます:
using ::testing::ExpectationSet;
...
ExpectationSet all_inits;
for (int i = 0; i < element_count; i++) {
all_inits += EXPECT_CALL(foo, InitElement(i));
}
EXPECT_CALL(foo, Bar())
.After(all_inits);
これは,全ての要素が初期化された後でのみ(ただし,要素の初期化される順番には関心がありません),Bar() を呼び出すことができる,ということを意味します.
.After() で利用した後に ExpectationSet を変更しても,.After() の意味は変わりません.
シーケンシャルな Expectation の長い連鎖がある場合は,シーケンスを利用して順序を指定するのが簡単です.この場合,連鎖 の中の各 Expectation に別々の名前を与える必要がありません.同じシーケンスに属する呼び出しは全て,指定された順番で呼び出される必要があります.
using ::testing::Sequence;
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"));
これは,GetSize() および Describe() の後でのみ(これらの順序は任意です), Reset() が呼び出されることを意味します.
シーケンスに含まれる Expectation の数が多い場合には,便利な方法があります:
using ::testing::InSequence;
{
InSequence dummy;
EXPECT_CALL(...)...;
EXPECT_CALL(...)...;
...
EXPECT_CALL(...)...;
}
これは,dummy と同じスコープ内にあるすべての呼び出しが,その順序で発生する必要があることを意味します.dummy という名前には,特に意味はありません.
Google Mock は,モックオブジェクトがデストラクトされた際に,その Expectation を検証します.また,デストラクトよりも前のタイミングでそれを行うこともできます.
using ::testing::Mock;
...
// mock_obj の Expectation を検証して削除します.
// 成功した場合のみ true を返します.
Mock::VerifyAndClearExpectations(&mock_obj);
...
// mock_obj の Expectation を検証して削除します.
// ON_CALL() で設定されたデフォルト Action も削除されます.
// 成功した場合のみ true を返します.
Mock::VerifyAndClear(&mock_obj);
Google Mock が,特定のモックオブジェクトを検証しないようにすることもできます:
Mock::AllowLeak(&mock_obj);
Google Mock には,便利なモッククラステンプレートが定義されています.
class MockFunction<R(A1, ..., An)> {
public:
MOCK_METHODn(Call, R(A1, ..., An));
};
応用は, このレシピ を参照してください.
—gmock_catch_leaked_mocks=0 | 検証しないモックオブジェクトを失敗として報告しないようにします. |
—gmock_verbose=LEVEL | Google Mock メッセージの出力レベル(情報,警告,エラー)を設定します. |