Может ли Google Mock метод с возвращаемым типом умного указателя? - PullRequest
43 голосов
/ 01 октября 2011

У меня есть фабрика, которая возвращает умный указатель.Независимо от того, какой умный указатель я использую, я не могу заставить Google Mock издеваться над фабричным методом.

Объект mock - это реализация чистого абстрактного интерфейса, где все методы являются виртуальными.У меня есть прототип:

MOCK_METHOD0(Create, std::unique_ptr<IMyObjectThing>());

И я получаю:

"...gmock/gmock-spec-builders.h(1314): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'"

Определен тип, на который указывает умный указатель.

И я получаю, что он пытаетсядоступ к одному из конструкторов, объявленных закрытыми, но я не понимаю, почему.Когда это был std :: auto_ptr, в сообщении об ошибке говорилось, что не было конструктора копирования, что меня смущает.

В любом случае, есть ли способ Mock для метода, который возвращает умный указатель?Или есть лучший способ построить фабрику?Являюсь ли я единственным решением вернуть необработанный указатель (блеф ...)?

Моя среда - Visual Studio 2010 Ultimate и Windows 7. Я не использую CLI.

Ответы [ 3 ]

94 голосов
/ 18 июля 2012

Возможный обходной путь для устранения проблем, связанных с использованием mock-фреймворка Google с неконстантными копируемыми аргументами функций и значениями повтора, - это использование прокси-методов mock.1003 * таким образом, кажется более или менее философским вопросом, лично мне нравится, чтобы он принудил передачу права собственности):

class IFooInterface {
public:
    virtual void nonCopyableParam(std::unique_ptr<IMyObjectThing> uPtr) = 0;
    virtual std::unique_ptr<IMyObjectThing> nonCopyableReturn() = 0;
    virtual ~IFooInterface() {}
};

Подходящий класс-образец может быть определен так:

class FooInterfaceMock
: public IFooInterface {
public:
    FooInterfaceMock() {}
    virtual ~FooInterfaceMock() {}

    virtual void nonCopyableParam(std::unique_ptr<IMyObjectThing> uPtr) {
        nonCopyableParamProxy(uPtr.get());
    }
    virtual std::unique_ptr<IMyObjectThing> nonCopyableReturn() {
        return std::unique_ptr<IMyObjectThing>(nonCopyableReturnProxy());
    }


    MOCK_METHOD1(nonCopyableParamProxy,void (IMyObjectThing*));
    MOCK_METHOD0(nonCopyableReturnProxy,IMyObjectThing* ());
};

Вам просто нужно позаботиться о том, чтобы конфигурации (выполненные действия) для метода nonCopyableReturnProxy() возвращали либо NULL, либо экземпляр, динамически выделяемый в куче.


Есть ветка форума пользователей google-mock обсуждает эту тему, где один из сопровождающих заявляет, что структура google-mock не будет изменена для поддержки этого в будущем, утверждая, что их политика настоятельно не рекомендует использовать параметры std::auto_ptr.Как уже упоминалось, это ИМХО с философской точки зрения, и возможности фальшивой инфраструктуры не должны определять, какие интерфейсы вы хотите разрабатывать или можете использовать из сторонних API.

Как сказано, ответ описывает выполнимый обходной путь.

7 голосов
/ 31 января 2019

Я знаю, что это сообщение было давно, поэтому вы, вероятно, уже нашли ответ.

gmock ранее не поддерживал фиктивные функции, которые возвращали любой подвижный тип, включая умные указатели. Однако в апреле 2017 года компания gmock представила новый модификатор действия ByMove.

.

EXPECT_CALL(*foo_, Bar(_, )).WillOnce(Return(ByMove(some_move_only_object)));

где some_move_only_object может быть, например, std::unique_ptr.

Так что да, теперь gmock может имитировать функцию, которая принимает умный указатель.

0 голосов
/ 01 октября 2011

Для Google Mock в большинстве случаев требуется копирование параметров и возвращаемых значений проверяемых методов. Согласно документации boost , unique_ptr не копируется. У вас есть возможность вернуть один из классов интеллектуальных указателей, которые используют общее владение ( shared_ptr , connected_ptr и т. Д.) И, таким образом, копируются. Или вы можете использовать необработанный указатель. Поскольку рассматриваемый метод, по-видимому, является методом, создающим объект, я не вижу внутренней проблемы с возвратом необработанного указателя. Пока вы присваиваете результат некоторому общему указателю на каждом сайте вызовов, все будет в порядке.

...