2015-10-26 83 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

真棒,謝謝! :) –