我正在尝试为我编写的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,我认为这是不可行的。
现在测试网络代码必须是常见的,因此必须有一种通用的方法来处理这个问题而不包括我的应用程序的一半。这似乎是一个普遍的问题,但如果需要有关我的具体应用的更多细节,请告诉我。
答案 0 :(得分:1)
首先,您可能希望为类定义干净的接口(意思是pure abstract classes),因此模拟和交换它们不会有问题,比如说IClientConnection
。
然后,您可以明确声明您的依赖项,即将IClientConnection
工厂或IClientConnection
的实例传递给NetworkServer
构造函数。
在测试中,您现在可以实现IClientConnection
的模拟,并将其或其工厂(也可能是一个接口)传递给测试中的构造函数。也许,您可能希望使用智能指针(shared_ptr或Qt原生的东西),以便自动资源释放可以最大限度地减少错误。
如果您的软件增长并且您发现自己编写了大量手动依赖注入,则可以使用DI库。我最近开始使用review一些可用的C ++ DI库。
最后,您可能会使用模拟框架(例如googlemock)来模拟您的依赖项。