Search code examples
c++tddgoogletest

references are a pain for my mocks in TDD


I am new with c++/tdd, embraced gtest/gmock, and fell in love. One thing kind of puzzles me though. Are reference pointers really the way to go?

I find myself producing a lot of boiler plate injecting all mocks (even when I don't have any business mocking that behavior).

Example:

namespace
{
    class set_configuration_command_tests : public testing::Test
    {
        protected:

        void SetUp() override
        {
            _uart_peripheral = new uart8_peripheral_mock();
            _uart = new uart8_mock(*_uart_peripheral);
            _logger =  new logger_mock(*_uart);
            _mqtt_client = new mqtt_client_mock(*_logger);
            _set_configuration_command = new set_configuration_command(*_mqtt_cient);
        }

        void TearDown() override
        {
            delete _set_configuration_command;
        }

        uart8_peripheral_mock *_uart_peripheral;
        uart8_mock *_uart;
        logger_mock *_logger;
        mqtt_client_mock *_mqtt_cient;

        set_configuration_command *_set_configuration_command;
    };

    TEST_F(set_configuration_command_tests, execute_update_configuration)
    {
        // arrange
        // act
        // assert
    }
}

What I rather did here, is create my sut as

_mqtt_client = new mqtt_client_mock(nullptr); // will not compile of course
_set_configuration_command = new set_configuration_command(*_mqtt_cient);

All the other mocks, I don't need in this case.

Is this the drawback of using reference pointers? Or is there a better approach I should follow?


Solution

  • Found a better alternative. Providing interfaces (pure virtual classes) heavily reduces the need to provide an entire tree of mocks.

    e.g

    class flash_api : public iflash_api
    {
        public:
        flash_api(iflash_peripheral &flash_peripheral) : _flash_peripheral(flash_peripheral)
        {
        }
    
        virtual ~flash_api()
        {
        }
    }
    

    Before my mock inherited from flash_api directly. When I gave this class an interface too (`iflash_api') I can let my mock inherit from iflash_api, which gives me a parameter-less constructor.

    class flash_api_mock : public iflash_api
    {
        public:
        flash_api_mock()
        {
        }
    
        virtual ~flash_api_mock()
        {
        }
    }
    

    Then I can write my unit test based on the mocks I actually want to give behavior.

    class set_configuration_command_tests : public testing::Test
    {
        protected:
    
        void SetUp() override
        {
            _mqtt_cient = new mqtt_client_mock();
            _flash_api = new flash_api_mock();
            _set_configuration_command = new set_configuration_command(*_mqtt_cient, *_flash_api);
        }
    
        void TearDown() override
        {
            delete _set_configuration_command;
        }
    
        flash_api_mock *_flash_api;
        mqtt_client_mock *_mqtt_cient;
    
        set_configuration_command *_set_configuration_command;
    };