Search code examples
c++qtgoogletest

virtual function in derived class not getting called when testing with GoogleTest


I am having trouble with GoogleTest calling a virtual function that I have defined in my derived class.

I have created a class MyServer using Qt that is derived from QTcpServer. When I run this code outside of GoogleTest the program behaves as expected. When I create a project with GoogleTest incomingConnection in my class never gets called. The socket is accepted as if QTcpServer::incomingConnection receives the call.

MyThread will emit a signal ReadySocket() which is normally connected to whomever created MyServer. When testing I created a MyServerTester Class that would receive the signal and set a flag that I could assert on.

I can simplify the problem down to the following code set a breakpoint in incomingConnection, start the server, connect to it with a client. The connection will be accepted, MyServer::incomingConnection will not be entered, therfore MyThread will never be created.

Project:Server File:MyServer.h

class MyServer : public QTcpServer
{
    Q_OBJECT

public:
    MyServer(QObject *parent = 0);

protected:
    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;
}

Project:Server File:MyServer.cpp

#include "MyServer.h"

MyServer::MyServer(QObject *parent) : QTcpServer(parent) { }

void MyServer::incomingConnection(qintptr socketDescriptor)
{
    MyThread *thread = new MyThread(socketDescriptor, this);
    connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
}

Project:Server_Test File:main.cpp

#include <QtCore/QCoreApplication>
#include "gtest\gtest.h"
#include "..\Server\MyServer.h"

TEST(MyServer, Successful_Connection)
{
    MyServer server;
    server.listen(QHostAddress::AnyIPv4, 4444);
    QThread::sleep(30);
}

int main(int argc, char*argv[])
{
    QCoreApplication a(argc, argv);
    ::testing::InitGoogleTest(&argc, argv);
    RUN_ALL_TESTS();

    return a.exec()
}

Solution

  • The first observation is that these are not Unit Tests, are more integration tests, since they use the network and the Qt event loop.

    The problem is that you are testing Qt signals that need the Qt event loop (the a.exec() call) to be running. But in your main, you are actually running the tests before starting the event loop. I am not sure it is worthwhile to try to shoehorn the Qt event loop within gtest.

    I suggest another approach: use Qt Test, which is perfectly adapted to the Qt event loop, and has, for example, a very handy signal spy to verify signal propagation.