QObject::deleteLater 在我的 Qt 测试中没有按预期调用

QObject::deleteLater is not called as expected in my Qt Test

我正在测试一个共享库,其中包含对 deleteLater 的内部调用。 库中没有事件循环运行,因此应用程序的要求是有一个事件循环运行,以便所有内存都被正确释放。

但是在测试中,对象dtor没有按预期调用。

例如:

void test1() 
{
    Foo foo;
    QSignalSpy spy(&foo, SIGNAL(mySignal(Status)));

    foo.do(); // should trigger mySignal 

    QVERIFY(spy.wait(10000)); // event loop started for 10 s max
    QCOMPARE(spy.count(), 1);
    QList<QVariant> sig = spy.takeFirst();
    Foo::Status status = qvariant_cast<Foo::Status>(sig.at(0));

    QVERIFY2(status == Foo:Ok, "Failed");
}

class Foo 看起来像这样:

class Foo : public QObject
{
Q_OBJECT

// ... methods, signals, slots..

private slots:
 // this call is asynchronous (depends on a network reply)
 void myslot() {
     //..
     m_obj->deleteLater();
     emit mySignal(Foo:Ok);
  }
};

我在m_obj的dtor中添加了一些调试打印,并且在执行test1时没有调用它。

但是,如果我执行两次测试(通过添加一个 test2 插槽,它是 test1 的副本),那么它会被调用一次。

我的理解是,当发出信号时,它会停止间谍事件循环,然后永远不会调用 deleteLater。 之后,第二个事件循环在 test2 中开始,它处理来自前一个 test1 的未决删除。

是否正确? 谢谢。

是的,你是对的。由于 QSignalSpyFoo 位于同一个线程中,因此信号 mySignal 不是通过事件循环传递的,而是通过直接连接传递的。因此,事件循环在 myslot 中发出信号后立即停止。但是,由于 myslot 被同一个事件循环调用,因此当 myslot returns 时,仅控制 returns 到它。因此,当事件循环可能执行 deleteLater 请求的清理时,它已经停止了。

如果你想测试 m_obj 是否被正确清理,你可以创建一个额外的 QSignalSpy 并将其连接到每个 QObject 发出的 QObject::destroyed 信号当它被摧毁时。

但是,您需要在构造函数中或通过 setter 将 m_obj 作为对 Foo 的依赖项传递,而不是在 Foo 中构造它本身。

测试可能看起来像这样:

void test1()
{
    auto obj = new Obj{}; // will be assigned to `Foo::m_obj`
    Foo foo{obj};

    QSignalSpy deletion_spy(obj, &QObject::destroyed);
    QSignalSpy mysignal_spy(&Foo, &Foo::mySignal);

    QVERIFY(deletion_spy.wait(10000));
    QCOMPARE(deletion_spy.count(), 1); // verify that `obj` got deleted

    QCOMPARE(mysignal_spy.count(), 1);
    QList<QVariant> sig = spy.takeFirst();
    Foo::Status status = qvariant_cast<Foo::Status>(sig.at(0));

    QVERIFY2(status == Foo:Ok, "Failed");
}