簡體   English   中英

GoogleMock 模擬非虛擬函數

[英]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)如果構造器模板化。


這里有幾種方法(可能有很多)來解決這個問題:

  1. 您可以模板化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 )會起作用。

  2. 您可以定義一個默認模板參數:

     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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM