0

Suppose I have a method and I want to test it using gtest/gmock framework. This method calls another method inside itself using a Qt queued invoke:

void MyClass::handleFoo()
{
    // ...
    Q_ASSERT(QMetaObject::invokeMethod(this, "handleBar", Qt::QueuedConnection));
}

void MyClass::handleBar()
{
    _view.show();
}
TEST_F(MyTestSuite, MyTest)
{
    EXPECT_CALL(_viewMock, show()); // Fails with never called

    emit _myClassObj->foo();

    // Tried QCoreApplication::processEvents() -- does not help
}

Is there any way to do it? I think maybe I should just test these two handlers separately. But how can I test that the method handleFoo() will indeed call handleBar()?

JenyaKh
  • 2,040
  • 17
  • 25
  • 1
    And that `_view` of yours is a mocked object when called inside the `handleBar()` invocation? – ixSci Apr 24 '22 at 13:06
  • Yes, it is. Actually it worked all quite great before I realized that I should "move out" some execution from handleFoo() to be called after returning to the event loop, – JenyaKh Apr 24 '22 at 13:18
  • 1
    And if you use the direct connection in `invokeMethod` then it gets called? – ixSci Apr 24 '22 at 13:34
  • Yes, I have just double checked that when I use Qt::DirectConnection, the test succeeds, i.e. the mock is called. – JenyaKh Apr 24 '22 at 13:48
  • 1
    Then you need to find out why `QCoreApplication::processEvents()` didn't help you. If you aren't using threads then it should have helped, if you are using threads then you should call it on the corresponding thread. – ixSci Apr 24 '22 at 14:51
  • I don't use threads. – JenyaKh Apr 24 '22 at 15:01
  • I honestly don't know why processEvents() does not help. If I understand right it should synchronously call my handleBar() but it does not. – JenyaKh Apr 24 '22 at 15:03
  • Oh, I think I have guessed what the problem is! I do not have a QCoreApplication in my gtest main.cpp. Lol. I am not sure -- can I call the event loop without it? – JenyaKh Apr 24 '22 at 15:11
  • 1
    You need an event loop to work with the Qt plumbing properly. Either use `QEventLoop` or create a `QCoreApplication` application which will do it for you. – ixSci Apr 24 '22 at 15:28
  • I see. I will try and update on the result. Thank you for your time and help! – JenyaKh Apr 24 '22 at 15:31
  • 1
    I have created a QCoreApplication right in the beginning of my unit test, and then I called QCoreApplication::processEvents() at the end of the test and everything worked out. – JenyaKh Apr 28 '22 at 09:38
  • I discovered that sometimes QCoreApplication::processEvents() has to be called twice to fire the needed event. To cure this, I now use QCoreApplication::sendPostedEvents(&*_myClassObj); – JenyaKh Apr 29 '22 at 12:08

0 Answers0