Paymahn Moghadasian
Paymahn Moghadasian

Reputation: 10329

How to mock boost throwing an exception?

I have code which interacts with the filesystem using boost which looks like:

FileMigrater::migrate() const {
    //stuff
    try {
        boost::filesystem::create_direcotry(some_path_);
    } catch(const std::exception& e) {
        LOG(ERROR) << "Bad stuff happened";
        return MigrationResult::Failed;
    }
    //more stuff
}

I'm using gmock and gtest to write unit tests for the migrate method and I'd like to write a test for the case where boost throws an exception. Ideally, I'd like to write a unit test which looks something like (the syntax of this will be wrong because I'm new c++ in general):

TEST_F(MyTest, boost_exception_test) {
    ON_CALL(boost_mock, create_directory()).Throw(std::exception);

    EXPECT_EQ(Migration::Failed, migrater.migrate());
}

The problem is that I don't know how to create the boost_mock or even if that's the right approach to the problem.

Upvotes: 1

Views: 1090

Answers (1)

Antonio P&#233;rez
Antonio P&#233;rez

Reputation: 6982

Your testing approach is quite good. The point is that cannot mock free functions and boost::filesystem::create_directory() is one.

However, the documentation suggests an approach to work around it:

It's possible to use Google Mock to mock a free function (i.e. a C-style function or a static method). You just need to rewrite your code to use an interface (abstract class).

Instead of calling a free function (say, OpenFile) directly, introduce an interface for it and have a concrete subclass that calls the free function:

class FileInterface {
public:
 ...
 virtual bool Open(const char* path, const char* mode) = 0;
};
class File : public FileInterface {
public:
 ...
 virtual bool Open(const char* path, const char* mode) {
  return OpenFile(path, mode);
 }
};

Your code should talk to FileInterface to open a file. Now it's easy to mock out the function.

This may seem much hassle, but in practice you often have multiple related functions that you can put in the same interface, so the per-function syntactic overhead will be much lower.

If you are concerned about the performance overhead incurred by virtual functions, and profiling confirms your concern, you can combine this with the recipe for mocking non-virtual methods.

Upvotes: 1

Related Questions