[英]GoogleMock mocking non-virtual functions
我們正在為現有代碼庫編寫單元測試。 我們使用 Google Test/Google Mock 進行測試,C++11 和帶有 gcc 編譯器的 Eclipse CDT。
我們的一個類聚合了一個 Boost Socket。 它使用它作為實例,但幸運的是我們可以修改現有的代碼庫,我將其更改為指針並將套接字作為依賴項注入。 所以我開始模擬對套接字的調用,但有一個問題:Boost 函數是非虛擬的。
我找到了展示如何使用高性能依賴注入來模擬非虛擬函數的文檔。 然而,試圖按所示實施它,但沒有成功。 例如,文檔說“模板化你的代碼”。 所以對於我們使用boost socket的類,我遵循了他們的例子。 我插入:
template <class boost::asio::ip::udp::socket>
這應該讓我們插入我們的模擬類而不是具體的 Boost 類。 我在類之前和在接受套接字的構造函數之前分別嘗試過,在頭文件和實現文件中。 在每個地方,我都會遇到大量錯誤,其中大部分都與構造函數調用“沒有匹配的函數調用”類似。
顯然,我做錯了什么。 有人知道某個地方的完整示例嗎?
更新:根據請求,這是我們目前擁有的:
GoogleMock 模擬非虛擬函數
class PIngester : public IPIngester{
public:
// this is the method that takes the socket. It is the constructor, and the socket
// is a default parameter so the existing code will still work. We added the socket
// as a parameter specifically for unit testing. If no socket is provided, the
// constructor creates one. It only will ever create a concrete Boost
// Socket, not a mock one.
PIngester(boost::asio::io_service& ioService, Band band,
std::unique_ptr<boost::asio::ip::udp::socket> socket = std::unique_ptr<boost::asio::ip::udp::socket>(nullptr));
...
更新 2
我為模板定義了一個泛型類類型,但這破壞了現有的代碼。 這是我當前的版本:
class PIngester : public IPIngester{
public:
template <class Socket>
PIngester(boost::asio::io_service& ioService, Band band,
std::unique_ptr<Socket> socket = std::unique_ptr<Socket>(nullptr));
...
我認為它可能會對默認參數產生影響,但我不能確定。 錯誤消息不是很有幫助:
error: no matching function for call to ‘foonamespace::PIngester::PIngester(boost::asio::io_service&, foonamespace::Band&)’
new PIngester(ioService, band));
此錯誤消息來自現有代碼; 它似乎無法識別默認參數。
更新 3
我已經放棄了這種方法,而是決定編寫一個 Boost Socket Wrapper。 包裝器將保存實際的 Socket 實例,其方法將直接傳遞到實際的 Socket。 包裝器的功能將是虛擬的,我的模擬對象將從包裝器繼承。 然后我的模擬對象將模擬包裝器的虛函數。
正如您所注意到的,問題在於編譯器無法推斷Socket
在這里表示的任何類型:
class PIngester : public IPIngester{
public:
template <class Socket>
PIngester(boost::asio::io_service& ioService, Band band,
std::unique_ptr<Socket> socket = std::unique_ptr<Socket>(nullptr));
...
如果您嘗試構造此類的對象而不指定第三個參數(如new PIngester(ioService, band)
),那么Socket
究竟是什么?
現在,有沒有辦法來明確指定調用構造函數時任何模板參數,所以你不能這樣做new PIngester<boost::asio::ip::udp::socket>(ioService, band)
如果構造器模板化。
這里有幾種方法(可能有很多)來解決這個問題:
您可以模板化PIngester
類本身:
template <class Socket> class PIngester : public IPIngester{ public: PIngester(boost::asio::io_service& ioService, Band band, std::unique_ptr<Socket> socket = std::unique_ptr<Socket>(nullptr)); ...
然后調用new PIngester<boost::asio::ip::udp::socket>(ioService, band)
(或者你的模擬類代替boost::asio::ip::udp::socket
)會起作用。
您可以定義一個默認模板參數:
class PIngester : public IPIngester{ public: template <class Socket = boost::asio::ip::udp::socket> PIngester(boost::asio::io_service& ioService, Band band, std::unique_ptr<Socket> socket = std::unique_ptr<Socket>(nullptr)); ...
然后PIngester(ioService, band)
將始終使用這個默認的 Boost 類,如果你想在測試中使用它,你需要顯式傳入一些代表模擬類的唯一指針的socket
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.