我有一个返回智能指针的工厂。无论我使用什么智能指针,我都无法让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。
答案 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等)的智能指针类之一,因此可以复制。或者您可以使用原始指针。由于所讨论的方法显然是构造对象的方法,因此我发现返回原始指针没有固有的问题。只要您将结果分配给每个呼叫站点的某个共享指针,您就可以了。