信号和槽的测试方法
Test method with Signals and Slots
我在 Qt 控制台应用程序中有以下两个简单的方法:
void Webservice::getFile(PostElement el)
{
parameter = ⪙
QUrl url(PATH);
QUrlQuery query;
query.addQueryItem(el.getParam(), el.getValue());
url.setQuery(query);
request.setUrl(url);
manager->get(request);
connect(manager, SIGNAL(finished(QNetworkReply*)), this,
SLOT(downloadCompleted(QNetworkReply*)));
}
void Webservice::downloadCompleted(QNetworkReply *reply)
{
QByteArray b = reply->readAll();
qDebug() << "Download completed!";
QFile file("/tmp/" + parameter->getValue());
file.open(QIODevice::WriteOnly);
file.write(b);
file.close();
reply->deleteLater();
}
我创建了一个 QTest 项目来测试 getFile
方法。
#include <QtTest>
#include <QCoreApplication>
// add necessary includes here
#include "webservice.h"
class WebserviceTest : public QObject
{
Q_OBJECT
public:
WebserviceTest();
~WebserviceTest();
private:
Webservice ws;
private slots:
void initTestCase();
void cleanupTestCase();
void getFile();
};
WebserviceTest::WebserviceTest()
{
}
WebserviceTest::~WebserviceTest()
{
}
void WebserviceTest::initTestCase()
{
}
void WebserviceTest::cleanupTestCase()
{
}
void WebserviceTest::getFile()
{
PostElement el{"file", "myPic.png"};
ws.getFile(el); // it should wait for the slot to be executed
}
QTEST_MAIN(WebserviceTest)
#include "tst_webservicetest.moc"
如你所见,它有信号和槽。如果我在我的原始项目中 运行 那个,我会看到 downloadCompleted
执行没有问题(因为它正在使用事件循环)。但在测试项目中,槽没有被调用。我在谷歌上搜索并找到了一些使用 QSignalSpy 的示例,但目前我还没有成功执行插槽。
如何让我的测试 "wait" 完成插槽?
这正是 QSignalSpy
的目的,它基本上旋转新的 QEventLoop
等待信号被执行。您的测试开始和异步操作,但它不会等待它完成,因此它会在操作进行时破坏对象。
Qt 测试也有一些内置超时,防止测试被卡住,这些超时在使用 QSignalSpy
时停止。在您的情况下,您需要从 class Webservice
发出新信号,表明下载已完成,例如(您也可以将参数传递给信号)如果需要:
class Webservice : public QObject {
Q_OBJECT
// Constructors etc.
signals:
void finished();
}
然后在你的void Webservice::downloadCompleted(QNetworkReply *reply)
结尾处:
emit finished();
在你的测试中是这样的:
PostElement el{"file", "myPic.png"};
// Prepare spy
QSignalSpy spy(&ws, SIGNAL(finished));
ws.getFile(el);
// Wait for result - by default this waits 5 seconds
spy.wait();
// Check if we had a timeout or actually signal was raised
QCOMPARE(spy.count(), 1);
我在 Qt 控制台应用程序中有以下两个简单的方法:
void Webservice::getFile(PostElement el)
{
parameter = ⪙
QUrl url(PATH);
QUrlQuery query;
query.addQueryItem(el.getParam(), el.getValue());
url.setQuery(query);
request.setUrl(url);
manager->get(request);
connect(manager, SIGNAL(finished(QNetworkReply*)), this,
SLOT(downloadCompleted(QNetworkReply*)));
}
void Webservice::downloadCompleted(QNetworkReply *reply)
{
QByteArray b = reply->readAll();
qDebug() << "Download completed!";
QFile file("/tmp/" + parameter->getValue());
file.open(QIODevice::WriteOnly);
file.write(b);
file.close();
reply->deleteLater();
}
我创建了一个 QTest 项目来测试 getFile
方法。
#include <QtTest>
#include <QCoreApplication>
// add necessary includes here
#include "webservice.h"
class WebserviceTest : public QObject
{
Q_OBJECT
public:
WebserviceTest();
~WebserviceTest();
private:
Webservice ws;
private slots:
void initTestCase();
void cleanupTestCase();
void getFile();
};
WebserviceTest::WebserviceTest()
{
}
WebserviceTest::~WebserviceTest()
{
}
void WebserviceTest::initTestCase()
{
}
void WebserviceTest::cleanupTestCase()
{
}
void WebserviceTest::getFile()
{
PostElement el{"file", "myPic.png"};
ws.getFile(el); // it should wait for the slot to be executed
}
QTEST_MAIN(WebserviceTest)
#include "tst_webservicetest.moc"
如你所见,它有信号和槽。如果我在我的原始项目中 运行 那个,我会看到 downloadCompleted
执行没有问题(因为它正在使用事件循环)。但在测试项目中,槽没有被调用。我在谷歌上搜索并找到了一些使用 QSignalSpy 的示例,但目前我还没有成功执行插槽。
如何让我的测试 "wait" 完成插槽?
这正是 QSignalSpy
的目的,它基本上旋转新的 QEventLoop
等待信号被执行。您的测试开始和异步操作,但它不会等待它完成,因此它会在操作进行时破坏对象。
Qt 测试也有一些内置超时,防止测试被卡住,这些超时在使用 QSignalSpy
时停止。在您的情况下,您需要从 class Webservice
发出新信号,表明下载已完成,例如(您也可以将参数传递给信号)如果需要:
class Webservice : public QObject {
Q_OBJECT
// Constructors etc.
signals:
void finished();
}
然后在你的void Webservice::downloadCompleted(QNetworkReply *reply)
结尾处:
emit finished();
在你的测试中是这样的:
PostElement el{"file", "myPic.png"};
// Prepare spy
QSignalSpy spy(&ws, SIGNAL(finished));
ws.getFile(el);
// Wait for result - by default this waits 5 seconds
spy.wait();
// Check if we had a timeout or actually signal was raised
QCOMPARE(spy.count(), 1);