3

我正在尝试为我编写的 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,我认为这是不可行的。

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

4

1 回答 1

1

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

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

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

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

最后,您可能会通过使用模拟框架(例如googlemock )来模拟您的依赖项,从而走得更远。

于 2014-01-03T00:02:44.837 回答