Использование Google Test с QNetworkAccessManager никогда не выдает finished
Я пытаюсь создать тест, который будет использовать QNetworkAccessManager для общения с нашим RESTful api. Все, что я хочу сделать, это захватить простой объект JSon с помощью QNetworkAccessManager. Мой код выглядит так:
Connection::Connection(QString const &username, QString const &password, QString const &url, QString const &api) :
_user(username), _pass(password), _url(url) {
_manager = new QNetworkAccessManager(this);
QObject::connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveReply(QNetworkReply*)));
QNetworkRequest request;
request.setUrl(QUrl(_url.append(api)));
request.setRawHeader("Authorization", QString("Basic ").append(QString("%1:%2").arg(_user).arg(_pass)).toUtf8());
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
QNetworkReply *reply = _manager->get(request);
}
void Connection::Connection(QNetworkReply *reply) {
//do some validation of the reply...
_data = QJsonDocument::fromJson(reply->readAll());
}
QJsonDocument Connection::data() const {
return _data;
}
...
#include <gtest/gtest.h>
#include "Connection.h"
#include <QApplication>
TEST(ConnectionTest, creation) {
int argc = 0;
char *argv = 0;
QApplication a(argc, &argv);
Connection *connect = new Connection("user","abc123", https://mytest.com/", "api/");
connect->deleteLater();
while (connect->data().isEmpty()) {
//loop forever
}
}
Первоначально я тестировал, имея соединение также быть QWidget. Готовый сигнал будет отображаться только в том случае, если я вызову connection->show(); затем я должен закрыть виджет вручную, и тест завершится. Однако это не очень полезно для автоматизированного модульного тестирования.
Если я использую описанный выше цикл while, чтобы дождаться, пока _data не будет установлена на что-то, то с QNetworkAccessManager никогда ничего не происходит, и он петляет вечно.
Есть ли какой-то вызов, который должен произойти, прежде чем что-то сдвинется с места? Почему - > show() 'работает?'1 ответ:
Вы не вращаете цикл событий, поэтому не ожидайте, что что-то асинхронное будет работать вообще.
Вам нужно добавить сигнал к классу
Connection
, который указывает, когда это сделано, и использовать этот сигнал, чтобы выйти из цикла событий:TEST(ConnectionTest, creation) { int argc = 0; char *argv = 0; QCoreApplication app(argc, &argv); // No need to allocate the connection on the heap! Connection connection("user", "abc123", "https://mytest.com/", "api/"); QObject::connect(&connection, &Connection::finished, &app, &QCoreApplication::quit()); app.exec(); }
Можно добавить экземпляр
QApplication
в качестве члена классаConnectionTest
.Также нет необходимости удваивать количество выделений кучи, имея член
QNetworkAccessManager * manager
. Вы можете иметь его в качестве постоянного члена:class Connection : public QObject { Q_OBJECT QNetworkAccessManager manager; Q_SLOT void receiveReply(QNetworkReply *) { ... emit finished(); } public: explicit Connection(const QString & user, const QString & password, const QUrl & url, const QString & path, QObject * parent = 0) : QObject(parent) { ... } Q_SIGNAL void finished(); };