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:
EXPECT_CALL
, you can easily test how your code uses the File
.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
in the same directory contains some complete examples. Here's one of them, showing how to simulate Write()
errors:
#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.
#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)); }
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:
Please see the Svala project for a gMock-based Bigtable implementation.
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.