如何对依赖Asio的一段代码进行单元测试?

rui*_*eco 4 c++ sockets unit-testing network-programming boost-asio

我有一个包含 Asio 的类。它的目的是模拟域和 TCP 套接字上的通信,但我对自动化单元测试感到困惑。我查看了FakeIt,但它只测试虚拟方法,GoogleMocks建议对我的代码进行模板化,以便我可以通过单元测试的 MockAsio 实现和生产中的真实 Asio。

还有其他方法对网络代码进行单元测试吗?伪造域和 TCP 套接字而不是运行整个堆栈?如果我使用 GoogleMock,为什么要使用一个使用 GoogleMock 的类而不是我自己的实现来满足我的需要?

小智 6

我最近遇到了同样的问题。由于 Asio 服务的方法(例如套接字read_some)通常不是虚拟的,因此简单的依赖注入是不可能的。据我了解,有两种可能的方法,这两种方法都在Google Mock Cook Book中进行了讨论:

高性能依赖注入(鸭子类型)

这里讨论。

这是@ruipacheco 在他的问题中已经提到的选项。

此选项需要对您的类进行模板化,但它引入的代码开销最少。

例如,如果您的类使用 Asio tcp 套接字,则构造它的实例将类似于:

asio::io_context io_context;
MyClass<asio::ip::tcp::socket> my_class(io_context);
Run Code Online (Sandbox Code Playgroud)

代码到接口

这里讨论。

这或多或少是@NiladriBose 所建议的。

此选项需要为每种服务类型(套接字、计时器等)编写一个 Asio 接口和一个 Asio 具体适配器!尽管如此,它是最通用和最强大的一个(并且它不需要像前一个选项那样对您的类进行模板化)。

例如,如果您的类使用 Asio tcp 套接字,则构造它的实例将类似于:

asio::io_context io_context;
AsioSocket socket(io_context);
MyClass my_class(socket);
Run Code Online (Sandbox Code Playgroud)

工厂强化

如果您的类使用 Asio 服务的多个实例(多个套接字、计时器等),那么创建一个抽象的 Asio 服务工厂可能会更好。该工厂将在其构造函数中接收 an 方法io_context,并导出make_socketmake_timer等等...方法。

然后,构建类的实例将类似于:

AsioFactory asio_factory(io_context);
MyClass my_class(asio_factory);
Run Code Online (Sandbox Code Playgroud)

最后,关于:

如果我使用 GoogleMock,为什么要使用一个使用 GoogleMock 的类而不是我自己的实现来满足我的需要?

请参阅此内容以了解模拟对象和伪造对象之间的区别。一般来说,我认为模拟对象需要更少的努力。另请参阅此内容以了解如何将 Google 模拟类与假类合并。