QSignalSpy::wait(...) fails, when QTest::qWait(...) succeeds

1.3k views Asked by At

It's a confusing situation i'm in. While testing state transitions for a QStateMachine, the following code fails to spy on the signal that causes the transition.

// Test transition to SS_STARTING
QSignalSpy spy(test_obj_, SIGNAL(StateChanged(int)));

// emmit StateChanged signal
test_obj_->SetState(SS_STARTING); 
// Current state property should be SS_STARTING
QVERIFY(spy.wait()); //<--- fails test
QVERIFY(test_obj_->GetCurrentState() == SS_STARTING);
QCOMPARE(spy.count(), 1);

The following code passes the test!

// Test transition to SS_STARTING
QSignalSpy spy(test_obj_, SIGNAL(StateChanged(int)));

// emmit StateChanged signal
test_obj_->SetState(SS_STARTING); 
// Current state property should be SS_STARTING
QTest::qWait(20); //<--- passes test
QVERIFY(test_obj_->GetCurrentState() == SS_STARTING);
QCOMPARE(spy.count(), 1);

I can also verify externally that the signal is being emitted using dbus-monitor.

I can go ahead and use QTest::qWait, it's no big deal, but i'm just confused as to why spy.wait isn't working.

Cheers, Simon

1

There are 1 answers

0
eyllanesc On BEST ANSWER

Your test is incorrect, as soon as you set setState() the signal is emitted, so spy.wait() will no longer receive it. So the idea is to emit the signal a moment after spy.wait() starts using a QTimer:

// Test transition to SS_STARTING
QSignalSpy spy(test_obj_, SIGNAL(StateChanged(int)));
// emmit StateChanged signal
// test_obj_->SetState(SS_STARTING); 
QTimer::singleShot(0, [test_obj_](){ test_obj_->setState(SS_STARTING);}); // <----
QVERIFY(spy.wait());
QVERIFY(test_obj_->GetCurrentState() == SS_STARTING);
QCOMPARE(spy.count(), 1);

In its second example, the QTest::qWait() is not necessary because the status changed synchronously