GMock: возврат значения в параметре

Есть интерфейс вида

struct Interface
{
    virual int get_param(int id) const = 0;
    virual bool set_param(int id, int value) = 0;
    
    virual bool read_block(int id, block_type& value) const = 0;
    virual bool write_block(int id, const block_type& value) = 0;
    
    virtual ~Interface() = default;
};

Для него написан Mock

struct InterfaceMock
    : public Interface
{
    MOCK_METHOD(int, get_param, (int id), (const, override));
    MOCK_METHOD(bool, set_param, (int id, int value), (override));
    
    MOCK_METHOD(bool, read_block, (int id, block_type& value), (const, override));
    MOCK_METHOD(bool, write_block, (int id, const block_type& value), (override));
};

Так же есть несколько CommandObject, смысл которых получить данные, обработать и вернуть результат.

struct Command
{
    virtual void exec(Interface* iface) const = 0;
};

Запнулся на тестировании тех, кто использует метод, возвращающий данные по ссылке:

struct ConcreteCommand
    : public Command
{
    void exec(Interface* iface) const override
    {
        // get some params
        auto param = iface->get_param(...);
        // get data
        block_type block;
        iface->read_block(..., block);
        
        // process data
        ....
        
        // set params
        iface->set_param(...);
    }
}

То есть мне из теста нужно установить данные и затем проверить результат обработки

Как это можно сделать?

UPD_0:
в "Actions / SideEffects" eсть ::testing::SetArgReferee, но что то не вижу информации о lifetime объектов передаваемых таким способом.

UPD_1:
Способ с SetArgReferee вроде бы работает, но есть опасения: что будет с block, если вызывать EXPECT_CALL в цикле?


using ::testing::_;
using ::testing::Return;
using ::testing::Sequence;
using ::testing::SetArgReferee;

class CommandTestFixture
    : public ::testing
{
    //...
}

TEST_F(CommandTestFixture, ConcreteCommand)
{
    InterfaceMock mock;
    Sequence s;
    std::unique_ptr<Interface> = std::make_unique<ConcreteCommand>;
    block_type block = ...;
    
    EXPECT_CALL(mock, get_param(...))
        .InSequence(s)
        .WillRepeatedly(Return(...));
    
    EXPECT_CALL(mock, read_block(..., _))
        .InSequence(s)
        .WillRepeatedly(SetArgReferee<1>(block));
    
    EXPECT_CALL(mock, set_param(...))
        .InSequence(s)
        .WillRepeatedly(Return(...));
}

Ответы (0 шт):