2015-10-26 92 views
1

我有代码使用boost它看起来像文件系统交互:如何模拟提升抛出异常?

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 
} 

我使用gmockgtest写为migrate方法的单元测试,我想编写一个测试的情况下其中boost引发异常。理想情况下,我想编写一个单元测试,它看起来像(这句法将是错误的,因为我在通用新的C++):

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

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

的问题是,我不知道如何创建boost_mock或者即使这是解决问题的正确方法。

+0

我的方法:默默坐在那里,有你的头像捂脸每当升压抛出这样一个异常 – sehe

回答

1

您的测试方法非常好。关键是不能模拟免费功能,boost::filesystem::create_directory()就是其中之一。

然而,documentation暗示的方法来解决它:

它可以使用谷歌模拟来模拟一个免费的功能(即一个 C风格的函数或静态方法)。你只需要重写你的 代码来使用一个接口(抽象类)。

而不是调用一个免费的功能(比如,的OpenFile)直接引入 它的接口,并有一个调用的自由 功能的具体子类的:

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); 
} 
}; 

您的代码应该跟FileInterface开一份文件。现在很容易嘲笑这个功能。

这看起来很麻烦,但实际上你经常有多个可以放在同一个接口中的相关函数,所以每个函数的语法开销要低得多。

如果您担心 虚拟功能所带来的性能开销,并且配置文件确认了您的问题,您可以将 与mocking non-virtual methods的配方结合使用。

+0

我'FileMigrater'类应该然后采取在'FileInterface'作为构造的依赖,对不对? –

+1

是的,你必须注入依赖关系。使用构造函数是常见的。如果您不想为每个实例保留一个引用,并且可以共享相同的'FileInterface'对象,则'FileMigrater'中也可以有一个静态成员。 –

+0

真棒,谢谢! :) –