2011-04-25 73 views
10

我正在寫一個C++類來包裝套接字(我知道有這個好的庫 - 我正在滾動自己的練習):單元測試C++方法,使標準庫調用模式

class Socket { 
public: 
    int init(void); // calls socket(2) 
    // other stuff we don't care about for the sake of this code sample 
}; 

這個類反過來被其他幾個人使用,我知道我可以用googlemock進行子類化和嘲諷的單元測試。

但我想開發這個類test first,目前有點卡住了。我不能在C標準庫(在這種情況下爲socket.h)上使用googlemock,因爲它不是C++類。 I could圍繞我需要的C標準庫函數創建一個簡單的C++包裝類,現在

class LibcWrapper { 
public: 
    static int socket(int domain, int type, int protocol); 
    static int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 
    static int listen(int sockfd, int backlog); 
    static int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 
    static ssize_t write(int fd, const void *buf, size_t count); 
    static int close(int fd); 
}; 

我可以嘲笑那個和單元測試我Socket類(現在可能需要被重新命名Network或類似)。 LibcWrapper也可以用於其他類,因爲它只提供一堆類方法,所以本身不需要進行單元測試。

這對我來說聽起來很好。我是否回答了我自己的問題,或者是否存在標準模式來測試C++中的這種開發?

+2

googlemock [食譜](http://code.google.com/p/googlemock/wiki/CookBook#Mocking_Free_Functions)建議在你情況類似的東西。 – beduin 2011-04-25 15:01:26

+0

@Beduin:讓這個答案,我會投票。 :) – 2011-04-25 15:29:49

+0

@Josh格洛弗:完成)) – beduin 2011-04-25 15:38:58

回答

4

我可能會通過套接字接口(即基類)和實現該基類的測試版本來嘲笑它。

您可以通過幾種方法來完成此操作,例如,最簡單的方法是使用C++接口來指定整個套接字API。

class ISocket 
    { 
    public: 
     virtual int socket(int domain, int type, int protocol) = 0; 
     virtual int bind(int sockfd...) = 0; 
     // listen, accept, write, etc    
    }; 

然後提供一個通過的BSD套接字庫

class CBsdSocketLib : public ISocket 
    { 
    public: 
     // yadda, same stuff but actually call the BSD socket interface 
    }; 


    class CTestSocketLib : public ISocket 
    { 
    public: 
     // simulate the socket library 
    }; 

工作通過編碼對你可以創建你的測試版本做任何你喜歡的界面具體實施。

但是,我們可以清楚地看到,這第一遍很奇怪。我們正在包裝一個完整的圖書館,從描述對象的意義上講,它不是一個真正的課堂。

你寧願用插座和插座的製造方式來思考。這將更加面向對象。沿着這些線我將上面的功能分成兩個類。

// responsible for socket creation/construction 
    class ISocketFactory 
    { 
     virtual ISocket* createSocket(...) = 0; // perform socket() and maybe bind() 
    }; 

    // a socket 
    class ISocket 
    { 
     // pure virtual recv, send, listen, close, etc 
    }; 

爲現場直播:

class CBsdSocketFactory : public ISocketFactory 
    { 
     ... 
    }; 

    class CBsdSocket : public ISocket 
    { 
     ... 
    }; 

來進行測試:

class CTestSocketFactory : public ISocketFactory 
    { 
    }; 

    class CTestSocket : public ISocket 
    { 
    }; 

和獨立的BSD庫調用成有自己的責任,這兩個不同的類別。

+0

我很喜歡這種方法。謝謝! – 2011-04-25 15:28:43

2

我也使用過這種技術。注意Google Mock並不完全支持嘲弄靜態函數。 The FAQ explains that you should use an interface使用虛擬方法,您可以使用通常的Google Mock方式來覆蓋。

+0

謝謝!我接受了Doug T的例子,僅僅是因爲他提供了所有的細節,但你肯定會獲得googlemock FAQ鏈接的最高票數。 :) – 2011-04-25 15:30:45