Google 可以模拟具有智能指针返回类型的方法吗?

发布于 2024-12-07 11:57:43 字数 638 浏览 5 评论 0原文

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

I have a factory that returns a smart pointer. Regardless of what smart pointer I use, I can't get Google Mock to mock the factory method.

The mock object is the implementation of a pure abstract interface where all methods are virtual. I have a prototype:

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

And I get:

"...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>'"

The type pointed to in the smart pointer is defined.

And I get it's trying to access one of the constructors declared private, but I don't understand why. When this was an std::auto_ptr, the error said there was no copy constructor, which confuses me.

Anyway, is there a way to Mock a method that returns a smart pointer? Or is there a better way to build a factory? Is my only resolve to return a raw pointer (blech...)?

My environment is Visual Studio 2010 Ultimate and Windows 7. I'm not using CLI.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

御弟哥哥 2024-12-14 11:57:43

对于谷歌模拟框架的非(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() {}
};

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

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 参数。如前所述,恕我直言,这是一种哲学观点,模拟框架的功能不应该引导您想要设计哪种接口,或者您可以从第 3 方 API 使用哪种接口。

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

A feasible workaround for google mock framework's problems with non (const) copyable function arguments and retun values is to use proxy mock methods.

Suppose you have the following interface definition (if it's good style to use std::unique_ptr in this way seems to be more or less a philosophical question, I personally like it to enforce transfer of ownership):

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

The appropriate mock class could be defined like this:

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* ());
};

You just need to take care, that configurations (Actions taken) for the nonCopyableReturnProxy() method return either NULL or an instance allocated dynamically on the heap.


There's a google-mock user forum thread discussing this topic where one of the maintainers states that the google-mock framework won't be changed to support this in future arguing that their policies strongly discourage the usage std::auto_ptr parameters. As mentioned this is IMHO a philosophical point of view, and the capabilities of the mocking framework shouldn't steer what kind of interfaces you want to design or you can use from 3rd party APIs.

As said the answer describes a feasible workaround.

没有伤那来痛 2024-12-14 11:57:43

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

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

I know this post was from a long time ago, so you've probably discovered the answer by now.

gmock previously did not support mock functions that returned any movable type, including smart pointers. However, in April 2017, gmock introduced a new Action modifier ByMove.

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

where some_move_only_object can be e.g. a std::unique_ptr.

So yes, now gmock can mock a function that takes a smart pointer.

离去的眼神 2024-12-14 11:57:43

在模拟类中放置与您想要的相同的

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


在下面的测试中,

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

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

in the mock class put same as you want

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


and in the test as below

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

if vs 2010 not support for lambda, you can use a functor

末が日狂欢 2024-12-14 11:57:43

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

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

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

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

I have recently discovered that returning smart pointers by mocked functions is still not very user friendly. Yes, the new action ByMove had been introduced, however it turns out it may be used only once during the test. So imagine you have a factory class to test that repeatedly returns unique_ptr to the newly created object.

Any attempt to .WillRepeatedly(Return(ByMove) or multiple ON_CALL with .WillByDefault(Return(ByMove) will result in the following error:

[ FATAL ] Condition !performed_ failed. A ByMove() action should only be performed once.

This is also clearly stated in the GMock Cookbook in the paragraph "Mocking Methods That Use Move-Only Types".

意中人 2024-12-14 11:57:43

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

Google Mock requires parameters and return values of mocked methods to be copyable, in most cases. Per boost's documentation, unique_ptr is not copyable. You have an option of returning one of the smart pointer classes that use shared ownership (shared_ptr, linked_ptr, etc.) and are thus copyable. Or you can use a raw pointer. Since the method in question is apparently the method constructing an object, I see no inherent problem with returning a raw pointer. As long as you assign the result to some shared pointer at every call site, you are going to be fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文