谷歌可以用智能指针返回类型模拟一个方法吗?

Mat*_*ton 46 c++ unit-testing smart-pointers googlemock

我有一个返回智能指针的工厂.无论我使用什么智能指针,我都无法让Google Mock嘲笑工厂方法.

模拟对象是纯抽象接口的实现,其中所有方法都是虚拟的.我有一个原型:

MOCK_METHOD0(Create, std::unique_ptr<IMyObjectThing>());
Run Code Online (Sandbox Code Playgroud)

我得到:

"...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>'"
Run Code Online (Sandbox Code Playgroud)

定义了智能指针中指向的类型.

我得到它试图访问一个声明私有的构造函数,但我不明白为什么.当这是一个std :: auto_ptr时,错误说没有复制构造函数,这让我很困惑.

无论如何,有没有办法模拟一个返回智能指针的方法?或者有更好的方法来建造工厂吗?我唯一的决心是返回一个原始指针(blech ......)?

我的环境是Visual Studio 2010 Ultimate和Windows 7.我没有使用CLI.

πάν*_*ῥεῖ 98

谷歌模拟框架的非(const)可复制函数参数和重新调整值的问题的可行解决方法是使用代理模拟方法.

假设您有以下接口定义(如果std::unique_ptr以这种方式使用的好样式似乎或多或少是一个哲学问题,我个人喜欢它强制执行所有权转移):

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

适当的模拟类可以像这样定义:

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* ());
};
Run Code Online (Sandbox Code Playgroud)

您只需要注意,该方法的配置(采取的操作)nonCopyableReturnProxy()返回或者NULL在堆上动态分配的实例.


有一个谷歌模拟用户论坛帖子讨论这个话题,其中一个维护者声明谷歌模拟框架将来不会改变以支持这一点,他们的政策强烈反对使用std::auto_ptr参数.如上所述,这是恕我直言,哲学观点,模拟框架的功能不应该指导您想要设计的接口类型,也不能使用第三方API.

如上所述,答案描述了一种可行的解决方法.

  • 当尝试模拟返回`std :: future`的函数时,此解决方法也有帮助. (3认同)
  • 为了完整起见,[关于如何解决代理的返回类型的链接](https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#mocking-methods-that-use- move-only-types)通过设置Factory,以避免仅生成nullptr unique_ptr (2认同)

小智 13

我知道这篇文章是很久以前的,所以您现在可能已经找到了答案。

gmock以前不支持返回任何可移动类型(包括智能指针)的模拟函数。但是,在2017年4月,gmock引入了一个新的Action修饰符ByMove

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

其中some_move_only_object可以例如是 std::unique_ptr.

所以是的,现在gmock可以模拟需要智能指针的函数。

  • 语法实际上是“ByMove(std::move(some_move_only_object))”。另请注意,返回“nullptr”还需要“ByMove(nullptr)”。 (4认同)
  • 这个答案指出了正确的方向,谢谢!以下是有关此主题的当前文档的链接:[github.com](https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#mocking-methods-that-use-仅移动类型) (2认同)

Vla*_*sev -6

在大多数情况下,Google Mock 要求模拟方法的参数和返回值是可复制的。根据boost 的文档, unique_ptr 是不可复制的。您可以选择返回使用共享所有权(shared_ptr、linked_ptr等)并因此可复制的智能指针类之一。或者您可以使用原始指针。由于所讨论的方法显然是构造对象的方法,因此我认为返回原始指针没有固有的问题。只要您将结果分配给每个调用站点的某个共享指针,就可以了。

  • 您不需要对类的接口进行任何更改,只是为了让它们与您的模拟框架一起使用。通常这是根本不可能的。这对我来说不是一个可以接受的解决方案! (39认同)
  • 我似乎无法接受工厂类返回原始指针。在这种情况下, unique_ptr 最有意义。它的设计部分是为了解决“将结果分配给*每个*调用站点上的某个共享指针”的问题。 (13认同)
  • 我认为这不是正确的答案,将所有内容更改为原始或共享所有权并不是仅仅为了进行测试的解决方案! (5认同)
  • 现在可以了,请参阅 [`Return(ByMove(...))`](https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#mocking-methods-that-仅使用移动类型) (4认同)