g3_content.md 5.55 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#### Mock(able) Files {#MockableFile}

Don't use Mockable Files except to simulate errors on File. For general testing
of File, see go/file-testing.

google3/file/testing/mockablefile/mockablefile.h defines a `MockableFile` class.
It wraps an arbitrary `File` object and makes its virtual methods "mockable",
meaning that by default they'll delegate to the underlying `File` while you have
the option to call `ON_CALL` or `EXPECT_CALL` to set expectations on them and/or
change their behavior. This gives you the best part of both a mock and a real
object:

*   The methods all have a working, default implementation. This can greatly
    reduce the amount of work needed to set up the mock object.
*   By setting expectations on the methods using `EXPECT_CALL`, you can easily
    test how your code uses the `File`.
*   By changing the methods' behavior (using `ON_CALL`), you can easily simulate
    file errors and thus test your error handling code.

`mockablefile.h` contains copious comments on the usage, and
[`mockablefile_test.cc`](http://google3/file/testing/mockablefile/mockablefile_test.cc)
in the same directory contains some complete examples. Here's one of them,
showing how to simulate `Write()` errors:

```cpp
#include "file/base/path.h"
#include "file/testing/mockablefile/mockablefile.h"

using ::file::testing::MockableFile;
using ::testing::_;
using ::testing::DoDefault;
using ::testing::Return;

// This test demonstrates using MockableFile to test code that handles
// File operation errors.  We want to test that WriteToFile() returns
// false when there is a Write() failure.  It's hard to cause such an
// error using a real File object, but easy to make MockableFile
// simulate it.
TEST(SampleTest, SimulateFileError) {
  // Creates a mockable_file object from a real File object.  The real
  // file is a local file in this example, but can also be any other
  // type of File.
  MockableFile* const mockable_file = new MockableFile(
      File::Create(file::JoinPath(FLAGS_test_tmpdir, "/test"), "w"));

  // Tells the mockable file to start failing from the second Write()
  // operation on.
  EXPECT_CALL(*mockable_file, Write)
      // By default, calls are delegated to the real File object.
      .WillOnce(DoDefault())
      // Simulates a write error from the second time on.
      .WillRepeatedly(Return(util::UnknownError("message")));

  // Exercises the code we want to test, letting it talk to the
  // MockableFile object instead of a real one.
  EXPECT_FALSE(WriteToFile(mockable_file));
}
```

`mockablefile.h` also defines a `MockableFileSystem` class that allows you to
register mockable files in the file system under the `/mockable` mount point,
which can then be opened by your code by name. Since `MockableFile` can wrap
**any** type of file, this means you can inject **any** type of file into the
file system for testing. For example, `google3/file/memfile/memfile.h` defines a
convenient in-memory file type `MutableStringFile`. Now, you can wrap a
`MutableStringFile` in a `MockableFile` and inject it using `MockableFileSystem`
in order to test error handling of File operations that want to open a file
themselves.

```cpp
#include "file/memfile/memfile.h" // you also need to depend on //file/memfile:memfile in your BUILD file
#include "file/testing/mockablefile/mockablefile.h"

using ::file::testing::MockableFile;
using ::file::testing::MockableFileSystem;
using ::testing::_;
using ::testing::DoDefault;
using ::testing::Return;

// This test demonstrates registering a MockableFile with (a.k.a.
// injecting it into) the file system and opening it by name later.
// We want to test that WriteToFileByName() returns false when there
// is a Write() failure.
TEST(SampleTest, RegisterMockableFile) {
  // Creates a mockable_file from a MutableStringFile.
  MockableFile* const mockable_file = new MockableFile(
      MutableStringFile("/foo/bar", new string,
                        TAKE_OWNERSHIP, DO_NOT_ALLOW_MMAP));

  // Creates a mockable file system so that we can inject
  // mockable_file into it.
  MockableFileSystem fs;

  // Injects mockable_file as "/mockable/foo/bar".
  const string kPath = "/mockable/foo/bar";
  EXPECT_CALL(fs, CreateFile(kPath, "w", _, _, _))
      .WillOnce(Return(mockable_file));

  // Tells the mockable file to start failing from the second Write()
  // operation on.
  EXPECT_CALL(*mockable_file, Write)
      // By default, calls are delegated to the real File object.
      .WillOnce(DoDefault())
      // Simulates a write error from the second time on.
      .WillRepeatedly(Return(util::error::UNKNOWN));

  // Exercises the code we want to test, letting it talk to the
  // MockableFile object instead of a real one.
  EXPECT_FALSE(WriteToFileByName(kPath));
}
```

#### Mock Network System Calls

Gary Morain (gmorain@) implemented mock network system calls such that you can
use gMock to control their behavior when testing code that invokes network
system calls. You can find the code here:

*   google3/net/util/network_system_call_interface.h - the interface.
*   google3/net/util/network_system_call.h - the real implementation.
*   google3/net/util/network_system_call_mock.h - the mock implementation.
*   google3/net/util/network_system_call_unittest.cc - the unit test and demo.

#### Mock Bigtable

Please see the
[Svala](https://sites.google.com/a/google.com/te-zrh/tools--technologies/gmock-bigtable)
project for a gMock-based Bigtable implementation.

#### Add Yours Here

Don't be shy! If you've created a mock class using gMock and think it would be
useful to other Googlers, write an entry about it on this wiki page so that
people can learn about it.