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 the QNetworkRequest, creating the QNetworkReply 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 the QNetworkReply::deleteLater() since I manually call the slot inside Downloader::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 returns false even though through debugging I can clearly see that emit signalDownloading() is executed plus the fact that the downloaded file has actually been downloaded almost instantly (2KB of data transfer on localhost 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.


  • Qt Champions 2017

    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?



  • Thanks for the reply. Will check it out.



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.