51

我有一个返回智能指针的工厂。无论我使用什么智能指针,我都无法让 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。

4

5 回答 5

101

对于 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 用户论坛主题讨论这个话题,其中一位维护者表示 google-mock 框架将来不会更改以支持这一点,他们认为他们的政策强烈反对使用std::auto_ptr参数。如前所述,恕我直言,这是一种哲学观点,模拟框架的功能不应该指导您要设计什么样的接口,或者您可以从 3rd 方 API 中使用。

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

于 2012-07-18T18:41:47.823 回答
33

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

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 可以模拟一个采用智能指针的函数。

于 2019-01-31T17:01:29.377 回答
4

在模拟类中放你想要的一样

MOCK_METHOD0(创建,std::unique_ptr());


在下面的测试中

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

如果 vs 2010 不支持 lambda,您可以使用仿函数

于 2019-08-15T04:00:34.917 回答
2

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

任何尝试.WillRepeatedly(Return(ByMove)或多次ON_CALL使用.WillByDefault(Return(ByMove)都将导致以下错误:

[致命]条件!执行_失败。ByMove() 动作只能执行一次。

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

于 2019-09-23T12:54:52.083 回答
-6

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

于 2011-10-01T16:33:27.970 回答