From 2eb31c185cfd6c8ae84dd6cad5bc6668901544a8 Mon Sep 17 00:00:00 2001 From: Xiaoyi Zhang Date: Tue, 27 Feb 2018 16:00:42 -0500 Subject: Add documentation for VariantWith. --- googlemock/docs/CheatSheet.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'googlemock/docs') diff --git a/googlemock/docs/CheatSheet.md b/googlemock/docs/CheatSheet.md index c6367fdd..f8bbbfe6 100644 --- a/googlemock/docs/CheatSheet.md +++ b/googlemock/docs/CheatSheet.md @@ -178,6 +178,8 @@ divided into several categories: |`Ne(value)` |`argument != value`| |`IsNull()` |`argument` is a `NULL` pointer (raw or smart).| |`NotNull()` |`argument` is a non-null pointer (raw or smart).| +|`VariantWith(m)` |`argument` is `variant<>` that holds the alternative of +type T with a value matching `m`.| |`Ref(variable)` |`argument` is a reference to `variable`.| |`TypedEq(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.| -- cgit v1.2.3 From 10e8ec2714a38cee7ec39118042e6a3fac589767 Mon Sep 17 00:00:00 2001 From: Gennadiy Civil Date: Wed, 18 Apr 2018 15:10:07 -0400 Subject: move only types docs --- googlemock/docs/CookBook.md | 205 ++++++++++++++++++++------------------------ 1 file changed, 93 insertions(+), 112 deletions(-) (limited to 'googlemock/docs') diff --git a/googlemock/docs/CookBook.md b/googlemock/docs/CookBook.md index c2565f1e..3737d030 100644 --- a/googlemock/docs/CookBook.md +++ b/googlemock/docs/CookBook.md @@ -2229,13 +2229,20 @@ versus ## Mocking Methods That Use Move-Only Types ## -C++11 introduced move-only types. A move-only-typed value can be moved from one object to another, but cannot be copied. `std::unique_ptr` is probably the most commonly used move-only type. +C++11 introduced *move-only types*. A move-only-typed value can be moved from +one object to another, but cannot be copied. `std::unique_ptr` is +probably the most commonly used move-only type. -Mocking a method that takes and/or returns move-only types presents some challenges, but nothing insurmountable. This recipe shows you how you can do it. +Mocking a method that takes and/or returns move-only types presents some +challenges, but nothing insurmountable. This recipe shows you how you can do it. +Note that the support for move-only method arguments was only introduced to +gMock in April 2017; in older code, you may find more complex +[workarounds](#LegacyMoveOnly) for lack of this feature. -Let’s say we are working on a fictional project that lets one post and share snippets called “buzzes”. Your code uses these types: +Let’s say we are working on a fictional project that lets one post and share +snippets called “buzzes”. Your code uses these types: -``` +```cpp enum class AccessLevel { kInternal, kPublic }; class Buzz { @@ -2247,59 +2254,46 @@ class Buzz { class Buzzer { public: virtual ~Buzzer() {} - virtual std::unique_ptr MakeBuzz(const std::string& text) = 0; - virtual bool ShareBuzz(std::unique_ptr buzz, Time timestamp) = 0; + virtual std::unique_ptr MakeBuzz(StringPiece text) = 0; + virtual bool ShareBuzz(std::unique_ptr buzz, int64_t timestamp) = 0; ... }; ``` -A `Buzz` object represents a snippet being posted. A class that implements the `Buzzer` interface is capable of creating and sharing `Buzz`. Methods in `Buzzer` may return a `unique_ptr` or take a `unique_ptr`. Now we need to mock `Buzzer` in our tests. - -To mock a method that returns a move-only type, you just use the familiar `MOCK_METHOD` syntax as usual: - -``` -class MockBuzzer : public Buzzer { - public: - MOCK_METHOD1(MakeBuzz, std::unique_ptr(const std::string& text)); - … -}; -``` - -However, if you attempt to use the same `MOCK_METHOD` pattern to mock a method that takes a move-only parameter, you’ll get a compiler error currently: - -``` - // Does NOT compile! - MOCK_METHOD2(ShareBuzz, bool(std::unique_ptr buzz, Time timestamp)); -``` - -While it’s highly desirable to make this syntax just work, it’s not trivial and the work hasn’t been done yet. Fortunately, there is a trick you can apply today to get something that works nearly as well as this. +A `Buzz` object represents a snippet being posted. A class that implements the +`Buzzer` interface is capable of creating and sharing `Buzz`es. Methods in +`Buzzer` may return a `unique_ptr` or take a +`unique_ptr`. Now we need to mock `Buzzer` in our tests. -The trick, is to delegate the `ShareBuzz()` method to a mock method (let’s call it `DoShareBuzz()`) that does not take move-only parameters: +To mock a method that accepts or returns move-only types, you just use the +familiar `MOCK_METHOD` syntax as usual: -``` +```cpp class MockBuzzer : public Buzzer { public: - MOCK_METHOD1(MakeBuzz, std::unique_ptr(const std::string& text)); - MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp)); - bool ShareBuzz(std::unique_ptr buzz, Time timestamp) { - return DoShareBuzz(buzz.get(), timestamp); - } + MOCK_METHOD1(MakeBuzz, std::unique_ptr(StringPiece text)); + MOCK_METHOD2(ShareBuzz, bool(std::unique_ptr buzz, int64_t timestamp)); }; ``` -Note that there's no need to define or declare `DoShareBuzz()` in a base class. You only need to define it as a `MOCK_METHOD` in the mock class. - -Now that we have the mock class defined, we can use it in tests. In the following code examples, we assume that we have defined a `MockBuzzer` object named `mock_buzzer_`: +Now that we have the mock class defined, we can use it in tests. In the +following code examples, we assume that we have defined a `MockBuzzer` object +named `mock_buzzer_`: -``` +```cpp MockBuzzer mock_buzzer_; ``` -First let’s see how we can set expectations on the `MakeBuzz()` method, which returns a `unique_ptr`. +First let’s see how we can set expectations on the `MakeBuzz()` method, which +returns a `unique_ptr`. -As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or `.WillRepeated()` clause), when that expectation fires, the default action for that method will be taken. Since `unique_ptr<>` has a default constructor that returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an action: +As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or +`.WillRepeated()` clause), when that expectation fires, the default action for +that method will be taken. Since `unique_ptr<>` has a default constructor +that returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an +action: -``` +```cpp // Use the default action. EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")); @@ -2307,32 +2301,13 @@ As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or EXPECT_EQ(nullptr, mock_buzzer_.MakeBuzz("hello")); ``` -If you are not happy with the default action, you can tweak it. Depending on what you need, you may either tweak the default action for a specific (mock object, mock method) combination using `ON_CALL()`, or you may tweak the default action for all mock methods that return a specific type. The usage of `ON_CALL()` is similar to `EXPECT_CALL()`, so we’ll skip it and just explain how to do the latter (tweaking the default action for a specific return type). You do this via the `DefaultValue<>::SetFactory()` and `DefaultValue<>::Clear()` API: - -``` - // Sets the default action for return type std::unique_ptr to - // creating a new Buzz every time. - DefaultValue>::SetFactory( - [] { return MakeUnique(AccessLevel::kInternal); }); - - // When this fires, the default action of MakeBuzz() will run, which - // will return a new Buzz object. - EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber()); +If you are not happy with the default action, you can tweak it as usual; see +[Setting Default Actions](#OnCall). - auto buzz1 = mock_buzzer_.MakeBuzz("hello"); - auto buzz2 = mock_buzzer_.MakeBuzz("hello"); - EXPECT_NE(nullptr, buzz1); - EXPECT_NE(nullptr, buzz2); - EXPECT_NE(buzz1, buzz2); +If you just need to return a pre-defined move-only value, you can use the +`Return(ByMove(...))` action: - // Resets the default action for return type std::unique_ptr, - // to avoid interfere with other tests. - DefaultValue>::Clear(); -``` - -What if you want the method to do something other than the default action? If you just need to return a pre-defined move-only value, you can use the `Return(ByMove(...))` action: - -``` +```cpp // When this fires, the unique_ptr<> specified by ByMove(...) will // be returned. EXPECT_CALL(mock_buzzer_, MakeBuzz("world")) @@ -2343,81 +2318,87 @@ What if you want the method to do something other than the default action? If y Note that `ByMove()` is essential here - if you drop it, the code won’t compile. -Quiz time! What do you think will happen if a `Return(ByMove(...))` action is performed more than once (e.g. you write `….WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first time the action runs, the source value will be consumed (since it’s a move-only value), so the next time around, there’s no value to move from -- you’ll get a run-time error that `Return(ByMove(...))` can only be run once. +Quiz time! What do you think will happen if a `Return(ByMove(...))` action is +performed more than once (e.g. you write +`….WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first +time the action runs, the source value will be consumed (since it’s a move-only +value), so the next time around, there’s no value to move from -- you’ll get a +run-time error that `Return(ByMove(...))` can only be run once. -If you need your mock method to do more than just moving a pre-defined value, remember that you can always use `Invoke()` to call a lambda or a callable object, which can do pretty much anything you want: +If you need your mock method to do more than just moving a pre-defined value, +remember that you can always use a lambda or a callable object, which can do +pretty much anything you want: -``` +```cpp EXPECT_CALL(mock_buzzer_, MakeBuzz("x")) - .WillRepeatedly(Invoke([](const std::string& text) { - return std::make_unique(AccessLevel::kInternal); - })); + .WillRepeatedly([](StringPiece text) { + return MakeUnique(AccessLevel::kInternal); + }); EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); ``` -Every time this `EXPECT_CALL` fires, a new `unique_ptr` will be created and returned. You cannot do this with `Return(ByMove(...))`. +Every time this `EXPECT_CALL` fires, a new `unique_ptr` will be +created and returned. You cannot do this with `Return(ByMove(...))`. -Now there’s one topic we haven’t covered: how do you set expectations on `ShareBuzz()`, which takes a move-only-typed parameter? The answer is you don’t. Instead, you set expectations on the `DoShareBuzz()` mock method (remember that we defined a `MOCK_METHOD` for `DoShareBuzz()`, not `ShareBuzz()`): +That covers returning move-only values; but how do we work with methods +accepting move-only arguments? The answer is that they work normally, although +some actions will not compile when any of method's arguments are move-only. You +can always use `Return`, or a [lambda or functor](#FunctionsAsActions): -``` - EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)); +```cpp + using ::testing::Unused; - // When one calls ShareBuzz() on the MockBuzzer like this, the call is - // forwarded to DoShareBuzz(), which is mocked. Therefore this statement - // will trigger the above EXPECT_CALL. - mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal), - ::base::Now()); + EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)) .WillOnce(Return(true)); + EXPECT_TRUE(mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal)), + 0); + + EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)) .WillOnce( + [](std::unique_ptr buzz, Unused) { return buzz != nullptr; }); + EXPECT_FALSE(mock_buzzer_.ShareBuzz(nullptr, 0)); ``` -Some of you may have spotted one problem with this approach: the `DoShareBuzz()` mock method differs from the real `ShareBuzz()` method in that it cannot take ownership of the buzz parameter - `ShareBuzz()` will always delete buzz after `DoShareBuzz()` returns. What if you need to save the buzz object somewhere for later use when `ShareBuzz()` is called? Indeed, you'd be stuck. +Many built-in actions (`WithArgs`, `WithoutArgs`,`DeleteArg`, `SaveArg`, ...) +could in principle support move-only arguments, but the support for this is not +implemented yet. If this is blocking you, please file a bug. -Another problem with the `DoShareBuzz()` we had is that it can surprise people reading or maintaining the test, as one would expect that `DoShareBuzz()` has (logically) the same contract as `ShareBuzz()`. +A few actions (e.g. `DoAll`) copy their arguments internally, so they can never +work with non-copyable objects; you'll have to use functors instead. -Fortunately, these problems can be fixed with a bit more code. Let's try to get it right this time: +##### Legacy workarounds for move-only types {#LegacyMoveOnly} -``` +Support for move-only function arguments was only introduced to gMock in April +2017. In older code, you may encounter the following workaround for the lack of +this feature (it is no longer necessary - we're including it just for +reference): + +```cpp class MockBuzzer : public Buzzer { public: - MockBuzzer() { - // Since DoShareBuzz(buzz, time) is supposed to take ownership of - // buzz, define a default behavior for DoShareBuzz(buzz, time) to - // delete buzz. - ON_CALL(*this, DoShareBuzz(_, _)) - .WillByDefault(Invoke([](Buzz* buzz, Time timestamp) { - delete buzz; - return true; - })); - } - - MOCK_METHOD1(MakeBuzz, std::unique_ptr(const std::string& text)); - - // Takes ownership of buzz. MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp)); - bool ShareBuzz(std::unique_ptr buzz, Time timestamp) { - return DoShareBuzz(buzz.release(), timestamp); + bool ShareBuzz(std::unique_ptr buzz, Time timestamp) override { + return DoShareBuzz(buzz.get(), timestamp); } }; ``` -Now, the mock `DoShareBuzz()` method is free to save the buzz argument for later use if this is what you want: +The trick is to delegate the `ShareBuzz()` method to a mock method (let’s call +it `DoShareBuzz()`) that does not take move-only parameters. Then, instead of +setting expectations on `ShareBuzz()`, you set them on the `DoShareBuzz()` mock +method: -``` - std::unique_ptr intercepted_buzz; - EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)) - .WillOnce(Invoke([&intercepted_buzz](Buzz* buzz, Time timestamp) { - // Save buzz in intercepted_buzz for analysis later. - intercepted_buzz.reset(buzz); - return false; - })); +```cpp + MockBuzzer mock_buzzer_; + EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)); - mock_buzzer_.ShareBuzz(std::make_unique(AccessLevel::kInternal), - Now()); - EXPECT_NE(nullptr, intercepted_buzz); + // When one calls ShareBuzz() on the MockBuzzer like this, the call is + // forwarded to DoShareBuzz(), which is mocked. Therefore this statement + // will trigger the above EXPECT_CALL. + mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal), 0); ``` -Using the tricks covered in this recipe, you are now able to mock methods that take and/or return move-only types. Put your newly-acquired power to good use - when you design a new API, you can now feel comfortable using `unique_ptrs` as appropriate, without fearing that doing so will compromise your tests. + ## Making the Compilation Faster ## -- cgit v1.2.3 From de47b0d30c1d2a2072eb1c2a2e852d6aaa028931 Mon Sep 17 00:00:00 2001 From: Gennadiy Civil Date: Mon, 11 Jun 2018 11:26:16 -0400 Subject: Rename "Primer.md" to "primer.md" and adjust links. Part of the documentaion rationalzation --- googlemock/docs/CheatSheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'googlemock/docs') diff --git a/googlemock/docs/CheatSheet.md b/googlemock/docs/CheatSheet.md index f8bbbfe6..d078b42e 100644 --- a/googlemock/docs/CheatSheet.md +++ b/googlemock/docs/CheatSheet.md @@ -349,7 +349,7 @@ You can make a matcher from one or more other matchers: ## Matchers as Test Assertions ## -|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](../../googletest/docs/Primer.md#assertions) if the value of `expression` doesn't match matcher `m`.| +|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](../../googletest/docs/primer.md#assertions) if the value of `expression` doesn't match matcher `m`.| |:---------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| |`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`. | -- cgit v1.2.3 From 8f87d00398228925b1542b81710a9015c8f68e7b Mon Sep 17 00:00:00 2001 From: Gennadiy Civil Date: Mon, 11 Jun 2018 11:40:35 -0400 Subject: Rename AdvancedGuide.md to advanced.md and adjust the links. Part of documentation rationalization work --- googlemock/docs/CheatSheet.md | 2 +- googlemock/docs/CookBook.md | 2 +- googlemock/docs/ForDummies.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'googlemock/docs') diff --git a/googlemock/docs/CheatSheet.md b/googlemock/docs/CheatSheet.md index d078b42e..d54dd16a 100644 --- a/googlemock/docs/CheatSheet.md +++ b/googlemock/docs/CheatSheet.md @@ -229,7 +229,7 @@ The `argument` can be either a C string or a C++ string object: `ContainsRegex()` and `MatchesRegex()` use the regular expression syntax defined -[here](../../googletest/docs/AdvancedGuide.md#regular-expression-syntax). +[here](../../googletest/docs/advanced.md#regular-expression-syntax). `StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide strings as well. diff --git a/googlemock/docs/CookBook.md b/googlemock/docs/CookBook.md index 3737d030..bd9f026b 100644 --- a/googlemock/docs/CookBook.md +++ b/googlemock/docs/CookBook.md @@ -3655,6 +3655,6 @@ This printer knows how to print built-in C++ types, native arrays, STL containers, and any type that supports the `<<` operator. For other types, it prints the raw bytes in the value and hopes that you the user can figure it out. -[Google Test's advanced guide](../../googletest/docs/AdvancedGuide.md#teaching-google-test-how-to-print-your-values) +[Google Test's advanced guide](../../googletest/docs/advanced.md#teaching-google-test-how-to-print-your-values) explains how to extend the printer to do a better job at printing your particular type than to dump the bytes. diff --git a/googlemock/docs/ForDummies.md b/googlemock/docs/ForDummies.md index 76910569..1e0fd416 100644 --- a/googlemock/docs/ForDummies.md +++ b/googlemock/docs/ForDummies.md @@ -187,7 +187,7 @@ sometimes causes the test program to crash. You'll still be able to notice that the test has failed, but it's not a graceful failure. A better solution is to use Google Test's -[event listener API](../../googletest/docs/AdvancedGuide.md#extending-google-test-by-handling-test-events) +[event listener API](../../googletest/docs/advanced.md#extending-google-test-by-handling-test-events) to report a test failure to your testing framework properly. You'll need to implement the `OnTestPartResult()` method of the event listener interface, but it should be straightforward. -- cgit v1.2.3 From 0b958a03e9f757c5f744f09fac2f82b6d896561b Mon Sep 17 00:00:00 2001 From: Gennadiy Civil Date: Mon, 11 Jun 2018 12:07:45 -0400 Subject: Removed "Documentation.md" not adding value and not consitent with internal docs --- googlemock/docs/FrequentlyAskedQuestions.md | 1 - 1 file changed, 1 deletion(-) (limited to 'googlemock/docs') diff --git a/googlemock/docs/FrequentlyAskedQuestions.md b/googlemock/docs/FrequentlyAskedQuestions.md index ccaa3d7a..23f7da03 100644 --- a/googlemock/docs/FrequentlyAskedQuestions.md +++ b/googlemock/docs/FrequentlyAskedQuestions.md @@ -607,7 +607,6 @@ See this [recipe](CookBook.md#mocking_side_effects) for more details and an exam If you cannot find the answer to your question in this FAQ, there are some other resources you can use: - 1. read other [documentation](Documentation.md), 1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics), 1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.). -- cgit v1.2.3 From 2eb43960076417a3dca33ea5ad58e3e9feaee6e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=9C=E4=BF=AE=E6=9D=8F?= Date: Fri, 20 Jul 2018 06:15:13 +0800 Subject: =?UTF-8?q?Replace=20"=E2=80=A6"=20with=20"..."(three=20dots)=20to?= =?UTF-8?q?=20fix=20warning=20C4819=20in=20Visual=20Studio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- googlemock/docs/CookBook.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'googlemock/docs') diff --git a/googlemock/docs/CookBook.md b/googlemock/docs/CookBook.md index bd9f026b..8809b0e7 100644 --- a/googlemock/docs/CookBook.md +++ b/googlemock/docs/CookBook.md @@ -2247,7 +2247,7 @@ enum class AccessLevel { kInternal, kPublic }; class Buzz { public: - explicit Buzz(AccessLevel access) { … } + explicit Buzz(AccessLevel access) { ... } ... }; @@ -2320,7 +2320,7 @@ Note that `ByMove()` is essential here - if you drop it, the code won’t compil Quiz time! What do you think will happen if a `Return(ByMove(...))` action is performed more than once (e.g. you write -`….WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first +`.WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first time the action runs, the source value will be consumed (since it’s a move-only value), so the next time around, there’s no value to move from -- you’ll get a run-time error that `Return(ByMove(...))` can only be run once. -- cgit v1.2.3 From 309e8a271e9aca1ef4aab899ce5d2d07c42123bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20K=C4=85kol?= Date: Wed, 25 Jul 2018 19:19:26 +0200 Subject: Updated broken and outdated URLs --- googlemock/docs/ForDummies.md | 2 +- googlemock/docs/FrequentlyAskedQuestions.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'googlemock/docs') diff --git a/googlemock/docs/ForDummies.md b/googlemock/docs/ForDummies.md index 1e0fd416..566a34e5 100644 --- a/googlemock/docs/ForDummies.md +++ b/googlemock/docs/ForDummies.md @@ -170,7 +170,7 @@ Admittedly, this test is contrived and doesn't do much. You can easily achieve t ## Using Google Mock with Any Testing Framework ## If you want to use something other than Google Test (e.g. [CppUnit](http://sourceforge.net/projects/cppunit/) or -[CxxTest](http://cxxtest.tigris.org/)) as your testing framework, just change the `main()` function in the previous section to: +[CxxTest](https://cxxtest.com/)) as your testing framework, just change the `main()` function in the previous section to: ``` int main(int argc, char** argv) { // The following line causes Google Mock to throw an exception on failure, diff --git a/googlemock/docs/FrequentlyAskedQuestions.md b/googlemock/docs/FrequentlyAskedQuestions.md index 23f7da03..9008c637 100644 --- a/googlemock/docs/FrequentlyAskedQuestions.md +++ b/googlemock/docs/FrequentlyAskedQuestions.md @@ -528,7 +528,7 @@ interface, which then can be easily mocked. It's a bit of work initially, but usually pays for itself quickly. This Google Testing Blog -[post](http://googletesting.blogspot.com/2008/06/defeat-static-cling.html) +[post](https://testing.googleblog.com/2008/06/defeat-static-cling.html) says it excellently. Check it out. ## My mock object needs to do complex stuff. It's a lot of pain to specify the actions. Google Mock sucks! ## -- cgit v1.2.3