2011-04-25 53 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