How to properly handle asynchronous events with Qt test framework? QSignalSpy::wait() returns false even though signal emitted during given time interval
-
Through a server that runs locally (I use
pyftpdlib
to make a local directory available through FTP with anonymous login) a class I have written downloads an archive. Triggering the download process (generation of theQNetworkRequest
, creating theQNetworkReply
and connecting the various signals related to all this) can be seen in the code snippet below:// Note that fileName and md5 are for something later on and are not important here void Downloader::download(QUrl source, QString fileName, QByteArray md5) { QNetworkRequest req(source); this->reply = this->manager->get(req); this->md5_download = md5; this->fileName = fileName; connect(this->reply, &QNetworkReply::finished, this, &Downloader::slotDownloadCompleted); connect(this->reply, &QIODevice::readyRead, this, &Downloader::slotDownloading); emit signalDownloading(); }
Note that I don't connect the
QNetworkAccessManager::finished()
to theQNetworkReply::deleteLater()
since I manually call the slot insideDownloader::slotDownloadComplete()
.My test is rather simple (for now):
void TestDownloader::testFtpDownload() { QSignalSpye downloadSpy(this->dw, &Downloader::signalDownloading); this->dw->download(QUrl("ftp://127.0.0.1:9999/update_0.45.tar.gz"), "update_0.45.tar.gz", QByteArray()); QVERIFY(downloadSpy.wait()); }
The downloading of the archive (here
update_0.45.tar.gz
) does succeed - I can confirm it both in the log of the FTP server and the fact that the archive is in the path of my test binary and valid (can be opened, decompressed etc.).However the thing that is bothering me is that no matter what timeout I set (I Tried with up to 40 seconds!) for
downloadSpy.wait()
it always returnsfalse
even though through debugging I can clearly see thatemit signalDownloading()
is executed plus the fact that the downloaded file has actually been downloaded almost instantly (2KB of data transfer onlocalhost
doesn't take more than 1ms in my experience).On several occasions now I am facing such problem of not being able to properly unit-test network functionality in my project because of the asynchronous nature of the network requests and replies. Even though I can clearly verify that things are working (by manually observing the network traffic and filesystem) I would still like to be able to do this properly and in a manner that can be used in a build server or in general an environment when you don't have the ability to manually check things.
-
Does this:
void TestDownloader::testFtpDownload() { QSignalSpy downloadSpy(this->dw, &Downloader::signalDownloading); QTimer::singleShot(0, dw, std::bind(&Downloader::download, dw, QUrl("ftp://127.0.0.1:9999/update_0.45.tar.gz"), "update_0.45.tar.gz", QByteArray())); QVERIFY(downloadSpy.wait()); }
fix it?