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

时间:2011-09-30 21:54:08

标签: c++ unit-testing smart-pointers googlemock

我有一个返回智能指针的工厂。无论我使用什么智能指针,我都无法让Google 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时,错误说没有复制构造函数,这让我很困惑。

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

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

5 个答案:

答案 0 :(得分:93)

google mock框架的非(const)可复制函数参数和retun值的问题的可行解决方法是使用代理模拟方法。

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

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 user forum thread正在讨论这个话题,其中一位维护者声明google-mock框架将来不会改变以支持这一点,他们的政策强烈反对使用std::auto_ptr参数。如上所述,这是恕我直言,哲学观点,模拟框架的功能不应该指导您想要设计的接口,也不能使用第三方API。

如上所述,答案描述了可行解决方法。

答案 1 :(得分:4)

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

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可以模拟需要智能指针的函数了。

答案 2 :(得分:1)

我最近发现,通过模拟函数返回智能指针仍然不是很友好。是的,已经引入了新动作ByMove,但事实证明,该动作只能在测试期间使用一次。因此,假设您有一个工厂类要测试,该类会反复向新创建的对象返回unique_ptr

任何尝试.WillRepeatedly(Return(ByMove)或多个ON_CALL.WillByDefault(Return(ByMove)的操作都会导致以下错误:

  

[FATAL]条件!performed_失败。 ByMove()操作只能执行一次。

GMock Cookbook在“使用仅移动类型的模拟方法”段落中也有明确说明。

答案 3 :(得分:0)

在模拟类中随便放置

MOCK_METHOD0(Create,std :: unique_ptr());


并在以下测试中

EXPECT_CALL(<mock-obj>, Create())
.WillOnce([]()->std::unique_ptr<IMyObjectThing>{
    return std::make_unique<IMyObjectThing>();
});

如果vs 2010不支持lambda,则可以使用函子

答案 4 :(得分:-6)

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