samedi 1 mai 2021

How to mock a function called in the constructor of a RAII class

Is there a way to correctly mock a function call which is used inside a constructor using Google Mock / Google Test? This for unit testing my RAII class.

What I tried is creating a Mock class which inherits from the implementation and have the MOCK_METHODx functions in place. Then in my test suite I want to put the EXPECT_CALL before the creation of the object, however, for the EXPECT_CALL the object already needs to be created.

// DeviceImpl.h
class DeviceImpl : public IDevice {
public: 
    explicit DeviceImpl(uint32_t deviceAddress);
    ~DeviceImpl() override;

    uint32_t read();
    void write(uint32_t data);

protected:
    /* Virtual forwarding functions to make gmock happy */
    virtual int _open_device(uint32_t deviceAddress) {
      return open_device(deviceAddress); // this is a C function
    }
    virtual int _close_device(int fd) {
      return close_device(fd); // this is a C function
    }
}

// DeviceImplMock.h
class DeviceImplMock : public DeviceImpl {
public:
    DeviceImplMock() : DeviceImpl(1) {};
    ~DeviceImplMock() override = default;

    MOCK_METHOD1(_open_device, int(uint32_t deviceAddress));
    MOCK_METHOD1(_close_device, int(int));
}

// DeviceTest.cc
class DeviceTestSuite : public ::testing::Test {
public:
    std::shared_ptr<DeviceImplMock> device_{nullptr};

    DeviceTestSuite() {
        // Determine how to fix the order problem.
        // For the EXPECT_CALL, and thus the mock, the objects already needs to be created.
        // However, creating the object (with std::make_shared) already calls the non-mocked function
        // What to do here?
        EXPECT_CALL(*device_.get(), _open_device(::testing::_)).WillOnce(Return(1));
        device_ = std::make_shared<DeviceImplMock>();
    }

    ~DeviceTestSuite() override {
        EXPECT_CALL(*device_.get(), _close_device(1)).WillOnce(Return(0));
    }
};

TEST_F(DeviceTestSuite, read) {
  // Test for device->read() here, etc...
}

Examples on how to unit test RAII classes using GMock are extremely welcome.

Roy

Aucun commentaire:

Enregistrer un commentaire