我正在为我的应用程序构建测试。目前,代码将所有数据库调用委托给单独的工作线程。当尝试测试函数时,我发现没有调用线程执行。
我看到我可以调用
QCoreApplication::exec()
来执行事件循环调用,但这会执行一些然后永远挂起。
Here,anda_skoa建议“使用在结果信号上退出的测试本地 QEventLoop 实例”,但我不知道该怎么做。
以下是当前代码的示例:
class TestUserService : public QObject
{
Q_OBJECT
const QString dbPath = "test_DB.db";
private slots:
void initTestCase()
{
DbManager* db = new DbManager();
QFuture<void> connection = db->connect(dbPath);
connection
.then([](){
qInfo() << "Database Connected!";
}).onFailed([](Exception e){
qDebug() << "Error initializing database" << e.what();
}); // None of this ever runs.
}
}
QFuture<void> DbManager::connect(const QString &path)
{
return QtConcurrent::run(DbThread::instance()->pool(), [path]() {
QSqlDatabase m_db = QSqlDatabase::addDatabase("QSQLITE", "main");
m_db.setDatabaseName(path);
if (!m_db.open())
{
throw Exception("Error connecting to the database");
}
});
}
此测试中的许多后续测试也是包装在返回 QFuture 的并发运行上的方法。但是,我可以看到没有任何 lambda 被执行,因为我可以看到没有生成调试日志,并且所有测试都失败了,因为值没有更改,因为它们的逻辑没有执行。
如果我在
QCoreApplication::exec()
末尾添加 initTestCase()
,则 lambda 会被执行,但它会永远挂在那里,并且不再执行任何其他操作。
我的应用程序一切正常,所以我确信缺少某些内容仅用于测试。
该怎么办?
因为你的问题不包含最小的可重现示例,所以我什至不想回答它,但我会尝试回答你的问题的标题,包括你对 Qt 中心的链接讨论的疑问:
“使用在结果信号上退出的测试本地 QEventLoop 实例”,但我不知道如何做到这一点
您可以熟悉QFutureWatcher,它允许使用信号和槽监视
QFuture
。我在下面显示了一个在 Qt 测试应用程序中使用本地事件循环的代码片段。它可能无法直接适用于您的问题,但希望能为您提供前进的想法。
QFutureWatcher<int> watcher;
QEventLoop loop;
QSignalSpy spy(&watcher, &QFutureWatcher<int>::finished);
QObject::connect(&watcher, &QFutureWatcherBase::finished,
&loop, &QEventLoop::quit, Qt::QueuedConnection);
auto future = QtConcurrent::run([](){
return 10;
});
watcher.setFuture(future);
QCOMPARE(spy.count(), 0);
loop.exec();
QCOMPARE(watcher.result(), 10);
QCOMPARE(spy.count(), 1);