谷歌模拟嘲笑非虚拟函数
GoogleMock mocking non-virtual functions
我们正在为现有代码库编写单元测试。我们使用Google Test/Google Mock进行测试,使用C++11和Eclipse CDT与gcc编译器进行测试。
我们的一个类聚合了一个升压套接字。它将其用作实例,但幸运的是我们可以修改现有的代码库,我将其更改为指针并将套接字作为依赖项注入。所以我开始模拟对套接字的调用,但有一个问题:Boost 函数是非虚拟的。
我找到了显示如何使用hi-perf 依赖注入来模拟非虚拟函数的文档。但是,尝试如图所示实现它并不成功。例如,文档说要"模板化你的代码"。因此,对于使用升压插座的班级,我遵循了他们的示例。我插入:
template <class boost::asio::ip::udp::socket>
这应该让我们插入我们的模拟类而不是具体的 Boost 类。我在类之前尝试了它,并在接受套接字的构造函数之前分别在标头和实现文件中尝试过。在每个地方,我都会收到大量错误,其中大多数错误都是沿着"没有匹配函数调用"构造函数调用的行。
显然,我做错了什么。有谁知道某处的完整示例?
更新:根据要求,这是我们目前拥有的:
谷歌模拟嘲笑非虚拟函数
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
在这里要表示的任何类型:
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
。
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 类型擦除的std::function与虚拟函数调用的开销
- 重写虚拟函数和继承
- 用纯虚拟函数兜圈子
- 为什么使用存储在虚拟方法表中的地址调用虚拟函数的函数会返回垃圾?
- 禁止子函数调用父级的抽象(或虚拟)函数
- 无法在子类中使用虚拟函数C++
- 无法在派生对象上运行虚拟函数
- 我可以调用从 main() 覆盖的虚拟函数吗?
- 在 C++ 中将函数获取和设置为虚拟函数
- 使用在堆栈上创建的对象调用虚拟函数
- 为什么在这种情况下不调用我的虚拟函数实现?
- 在C++中使虚拟函数私有化
- 模板继承类中的虚拟函数
- 为什么构造函数的虚拟函数调用有时有效,但其他调用却无效
- doxygenc++虚拟函数和实现
- 如何从派生类函数中调用虚拟函数