summaryrefslogtreecommitdiffstats
path: root/googlemock/docs/CookBook.md
diff options
context:
space:
mode:
Diffstat (limited to 'googlemock/docs/CookBook.md')
-rw-r--r--googlemock/docs/CookBook.md215
1 files changed, 98 insertions, 117 deletions
diff --git a/googlemock/docs/CookBook.md b/googlemock/docs/CookBook.md
index 3d07e68..8809b0e 100644
--- a/googlemock/docs/CookBook.md
+++ b/googlemock/docs/CookBook.md
@@ -1231,7 +1231,7 @@ that references the implementation object dies, the implementation
object will be deleted.
Therefore, if you have some complex matcher that you want to use again
-and again, there is no need to build it everytime. Just assign it to a
+and again, there is no need to build it every time. Just assign it to a
matcher variable and use that variable repeatedly! For example,
```
@@ -1403,7 +1403,7 @@ edge from node A to node B wherever A must occur before B, we can get
a DAG. We use the term "sequence" to mean a directed path in this
DAG. Now, if we decompose the DAG into sequences, we just need to know
which sequences each `EXPECT_CALL()` belongs to in order to be able to
-reconstruct the orginal DAG.
+reconstruct the original DAG.
So, to specify the partial order on the expectations we need to do two
things: first to define some `Sequence` objects, and then for each
@@ -2182,7 +2182,7 @@ the implementation object dies, the implementation object will be
deleted.
If you have some complex action that you want to use again and again,
-you may not have to build it from scratch everytime. If the action
+you may not have to build it from scratch every time. If the action
doesn't have an internal state (i.e. if it always does the same thing
no matter how many times it has been called), you can assign it to an
action variable and use that variable repeatedly. For example:
@@ -2229,77 +2229,71 @@ versus
## Mocking Methods That Use Move-Only Types ##
-C++11 introduced <em>move-only types</em>. A move-only-typed value can be moved from one object to another, but cannot be copied. `std::unique_ptr<T>` 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<T>` 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 {
public:
- explicit Buzz(AccessLevel access) { … }
+ explicit Buzz(AccessLevel access) { ... }
...
};
class Buzzer {
public:
virtual ~Buzzer() {}
- virtual std::unique_ptr<Buzz> MakeBuzz(const std::string& text) = 0;
- virtual bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) = 0;
+ virtual std::unique_ptr<Buzz> MakeBuzz(StringPiece text) = 0;
+ virtual bool ShareBuzz(std::unique_ptr<Buzz> 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<Buzz>` or take a `unique_ptr<Buzz>`. 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<Buzz>(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> 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<Buzz>` or take a
+`unique_ptr<Buzz>`. 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<Buzz>(const std::string& text));
- MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp));
- bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) {
- return DoShareBuzz(buzz.get(), timestamp);
- }
+ MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(StringPiece text));
+ MOCK_METHOD2(ShareBuzz, bool(std::unique_ptr<Buzz> 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<Buzz>`.
+First let’s see how we can set expectations on the `MakeBuzz()` method, which
+returns a `unique_ptr<Buzz>`.
-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<Buzz> to
- // creating a new Buzz every time.
- DefaultValue<std::unique_ptr<Buzz>>::SetFactory(
- [] { return MakeUnique<Buzz>(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<Buzz>,
- // to avoid interfere with other tests.
- DefaultValue<std::unique_ptr<Buzz>>::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<Buzz>(AccessLevel::kInternal);
- }));
+ .WillRepeatedly([](StringPiece text) {
+ return MakeUnique<Buzz>(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<Buzz>` will be created and returned. You cannot do this with `Return(ByMove(...))`.
+Every time this `EXPECT_CALL` fires, a new `unique_ptr<Buzz>` 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<Buzz>(AccessLevel::kInternal),
- ::base::Now());
+ EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)) .WillOnce(Return(true));
+ EXPECT_TRUE(mock_buzzer_.ShareBuzz(MakeUnique<Buzz>(AccessLevel::kInternal)),
+ 0);
+
+ EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)) .WillOnce(
+ [](std::unique_ptr<Buzz> 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<Buzz>(const std::string& text));
-
- // Takes ownership of buzz.
MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp));
- bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) {
- return DoShareBuzz(buzz.release(), timestamp);
+ bool ShareBuzz(std::unique_ptr<Buzz> 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<Buzz> 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<Buzz>(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<Buzz>(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 ##
@@ -3674,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.