【问题标题】:How to create dependency injection for testing QTcpSocket?如何创建依赖注入来测试 QTcpSocket?
【发布时间】:2013-12-25 19:15:23
【问题描述】:

我正在尝试为我编写的 Qt5 应用程序编写单元测试,但我对如何处理涉及网络的类感到困惑。我的主类包括一个 QTcpServer 子类,它覆盖 QTcpServer::incomingConnection 以创建一个 ClientConnection 对象并将其交给线程:

void NetworkServer::incomingConnection(qintptr socketDescriptor)
{
    QThread* clientThread = new QThread();
    ClientConnection* clientConnection = new ClientConnection(socketDescriptor);
    clientConnection->moveToThread(clientThread);

    // connect signals & slots to ClientConnection (removed for clarity)

    connect(clientThread, &QThread::started, clientConnection, &ClientConnection::run);
    clientThread->start();
}

ClientConnection类使用socketDescriptor在专用线程中打开一个新的QTcpSocket,从客户端接收数据,并进行处理。

ClientConnection::ClientConnection(int socketDescriptor, QObject *parent) :
    QObject(parent), socketDescriptor(socketDescriptor)
{
    tcpIncomingData = new QByteArray;
}

void ClientConnection::run()
{
    QTcpSocket socket;
    if(!socket.setSocketDescriptor(socketDescriptor)) {
           emit sig_error(socket.error());
           return;
       }

    if(socket.waitForReadyRead(5000)) {
        *tcpIncomingData = socket.readAll();
        qDebug() << "data received: " << tcpIncomingData;
    } else {
        qDebug() << "socket timed out!";
    }

    parseXmlData();

    socket.disconnectFromHost();
    socket.waitForDisconnected();
}

这门课还没有结束,但我现在想开始编写测试。我的问题是如何处理socketDescriptor。我假设我需要使用某种依赖注入,但如果不在测试用例中创建整个 QTcpServer,我认为这是不可行的。

现在测试网络代码一定很常见,所以必须有一种通用的方法来处理这个问题,而不包括我的一半应用程序。这似乎是一个普遍的问题,但如果需要有关我的特定应用程序的更多详细信息,请告诉我。

【问题讨论】:

    标签: c++ qt dependency-injection qtestlib


    【解决方案1】:

    首先,您可能希望为您的类定义干净的接口(即pure abstract classes),这样模拟和交换它们就不会成为问题,例如IClientConnection

    然后,您可以显式声明您的依赖关系,即将IClientConnection 工厂或IClientConnection 的实例传递给NetworkServer 构造函数。

    在您的测试中,您现在可以实现 IClientConnection 的模拟并将其或其工厂(也可能是接口)传递给测试中的构造函数。或许,您可能想要使用智能指针(shared_ptr 或 Qt 原生的东西),以便自动资源释放可以最大限度地减少错误。

    如果您的软件在增长并且您发现自己编写了大量手动依赖注入,您可能会使用 DI 库。我最近启动了一些可用的 C++ DI 库的review

    最后,您可能会通过使用模拟框架(例如 googlemock)来模拟您的依赖项来取得成功。

    【讨论】:

    • 附注您是否考虑过使用更高级别的网络组件?
    猜你喜欢
    • 2019-02-13
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多