繁体   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