views:

333

answers:

1

I would like to test an asynchronous request to a webserver. For that purpose I'm creating a simple unittest to quickly try a few lines of code:

void AsynchronousCall::testGet()
{
    QNetworkAccessManager *nam =  new QNetworkAccessManager(this);

    QUrl url("http://myownhttpserver.org");
    QNetworkRequest req(url);


    this->connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(reqFinished(QNetworkReply *)));
    QNetworkReply *rep = nam->get(req);

}

void AsynchronousCall::reqFinished(QNetworkReply *rep)
{
    qDebug() << rep->readAll();
    qDebug() << "finshed";
}

The problem is that reqFinished() is never reached. If I had a simple QEventLoop and and a loop.exec() just after the nam->get(req); the request is executed.

Any hint ? Do I have to use a loop.exec() in my every unittests ?

+2  A: 

If you want to test asynchronous behavior, you have to use QEventLoop or other class with similar functionality. I suggest you write helper method like this:

bool waitForSignal(QObject *sender, const char *signal, int timeout = 1000) {
    QEventLoop loop;
    QTimer timer;
    timer.setInterval(timeout);
    timer.setSingleShot(true);

    loop.connect(sender, signal, SLOT(quit()));
    loop.connect(&timer, SIGNAL(timeout()), SLOT(quit()));
    timer.start();
    loop.exec();

    return timer.isActive();
}

Then you can use it in your unit tests like this:

void AsynchronousCall::testGet()
{
    QNetworkAccessManager *nam =  new QNetworkAccessManager(this);

    QUrl url("http://myownhttpserver.org");
    QNetworkRequest req(url);


    this->connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(reqFinished(QNetworkReply *)));
    QNetworkReply *rep = nam->get(req);
    QVERIFY(waitForSignal(nam, SIGNAL(finished(QNetworkReply*)), 5000));
}

There are also other issues with your test:

  1. Tests that depend on network connection shouldn't be unit tests. You want your unit tests to be blazing fast, which is impossible to achieve with network connections.
  2. Your test doesn't really test anything: it just puts some info to debug console. You should define expectations and verify them using QVERIFY and QCOMPARE macros.
  3. QTest sucks IMHO. If you're creating test base from scratch, start using gtest + gmock instead.
chalup