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

问题描述 投票:2回答:2

我有一个包裹Asio的课程。它旨在模拟域和tcp套接字上的通信,但我不知道自动化单元测试。我查看了FakeIt,但它只测试虚拟方法,GoogleMocks suggests模板化我的代码,这样我就可以通过MockAsio实现单元测试和真正的Asio生产。

有没有其他方法来单元测试网络代码?假冒域和tcp套接字而不是运行整个堆栈?如果我使用GoogleMock,为什么要使用一个使用GoogleMock的课程,而不是我自己的实现,它可以满足我的需要?

c++ unit-testing sockets network-programming boost-asio
2个回答
1
投票

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

High performance dependency injection (duck typing)

讨论了here

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

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

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

asio::io_context io_context;
MyClass<asio::ip::tcp::socket> my_class(io_context);

Code to an interface

讨论了here

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

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

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

asio::io_context io_context;
AsioSocket socket(io_context);
MyClass my_class(socket);

Factory enhancement

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

然后,构建一个类的实例看起来像:

AsioFactory asio_factory(io_context);
MyClass my_class(asio_factory);

最后,关于:

如果我使用GoogleMock,为什么要使用一个使用GoogleMock的课程,而不是我自己的实现,它可以满足我的需要?

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


-1
投票

我假设你想模拟你的应用程序使用的ASIO包装器类。如果我的假设是正确的,那么说包装器有一个接口(过于简单 - 但大多数模拟框架需要一个纯粹的抽象,包括gmock) -

    class Iasio
    {
        virtual ~Iasio()
        {

        }
        virtual void send(std::vector<unsigned char> dataToSend) = 0;
        virtual std::vector<unsigned char > rcv() = 0;
    };

然后你有两个选项 - 1)模拟使用模拟框架,并在你的单元测试中使用模拟(将模拟注入使用contructor或accessor注入使用它的类)。对于每个单元测试场景,您需要设置模拟对象以返回预期的数据。

2)第一个选项有时可能比编写自己的测试模拟更麻烦,在这种情况下编写自己的测试模拟可以完全接受,从而为您提供更多控制。我说更多的控制因为模拟框架是通用的,它们可以在大多数常见场景中提供帮助,但复杂的场景可能需要定制的测试虚拟/模拟。

© www.soinside.com 2019 - 2024. All rights reserved.