Search code examples
c++mockingabstract-classgoogletest

googletest - mocking abstract class


I am learning mocking and using googletest I created MockServer class that should mock the abstract class IServer:

    class IServer
{
    virtual void writeData(QString buffer) = 0;
    virtual QByteArray readData() = 0;

protected:
    virtual ~IServer() = default;
};

class MockServer: public:: testing:: Test, public IServer
{
    MOCK_METHOD(void, writeData, (QString buffer), (override));
    MOCK_METHOD(QByteArray, readData, (), (override));
};

And now want to test the other class that uses it, however, I cannot initialize MockServer because it is an abstract class. How to solve this?

TEST_F(Serv_test, start)
{
    ?? MockServer mockServer; // <- how to declare it?
    EXPECT_CALL(mockServer, writeData(testing::_)).Times(1);
    EXPECT_CALL(mockServer, readData()).Return("testing");

    Car car (nullptr, mockServer);
}

Solution

  • You are confusing a few things:

    1. You are using a test fixture, but a test fixture needs to be a standalone class. You are mixing it with your mock class. You need to create a separate class for it.

    2. The Car class should take a parameter of type mock class (not the test fixture).

    3. .Return should be used inside WillOnce or WillRepeatedly among other places. You can't use it directly on EXPECT_CALL.

    I rewrote your code as follows:

    class IServer
    {
      public:
        virtual void writeData(QString buffer) = 0;
        virtual QByteArray readData() = 0;
    
    protected:
        virtual ~IServer() = default;
    };
    
    // Test fixture
    class Serv_test : public ::testing::Test {
    };
    
    // Mock class
    class MockServer: public IServer
    {
     public:
        MOCK_METHOD(void, writeData, (QString buffer), (override));
        MOCK_METHOD(QByteArray, readData, (), (override));
    };
    
    class Car{
      public:
      Car(int*, IServer* server):_server(server){
          _server->writeData("testing");
          _server->readData();
      }
    
      IServer* _server;
    };
    
    TEST_F(Serv_test, start)
    {
        MockServer mockServer; // <- how to declare it?
        EXPECT_CALL(mockServer, writeData(testing::_)).Times(1);
        EXPECT_CALL(mockServer, readData())
          .WillOnce(testing::Return("testing"));
    
        Car car (nullptr, &mockServer);
    }
    

    Working example here: https://godbolt.org/z/avsKdh37r