C++ 如何模拟方法返回已删除副本的对象?
如果一个接口有一个函数来创建一个具有已删除副本的对象,如何模拟该函数? Gmock似乎在内部使用对象的复制构造函数 例如 编译错误显示:C++ 如何模拟方法返回已删除副本的对象?,c++,unit-testing,googletest,gmock,C++,Unit Testing,Googletest,Gmock,如果一个接口有一个函数来创建一个具有已删除副本的对象,如何模拟该函数? Gmock似乎在内部使用对象的复制构造函数 例如 编译错误显示: gmock/gmock-spec-builders.h:1330:20: error: use of deleted function 'TTest::TTest(const TTest&)' T retval(value_); ... gmock/gmock-actions.h:190:52: error: use of deleted f
gmock/gmock-spec-builders.h:1330:20: error: use of deleted function 'TTest::TTest(const TTest&)'
T retval(value_);
...
gmock/gmock-actions.h:190:52: error: use of deleted function 'TTest::TTest(const TTest&)'
internal::BuiltInDefaultValue<T>::Get() : *value_;
...
gmock/internal/gmock-internal-utils.h:371:71: error: use of deleted function 'TTest::TTest(const TTest&)'
*static_cast<volatile typename remove_reference<T>::type*>(NULL));
gmock/gmock spec builders.h:1330:20:错误:使用了已删除的函数'TTest::TTest(const-TTest&)'
T retval(值u);
...
gmock/gmock actions.h:190:52:错误:使用已删除的函数“TTest::TTest(const TTest&)”
内部::内置indefaultvalue::Get():*值;
...
gmock/internal/gmock internal utils.h:371:71:错误:使用已删除的函数“TTest::TTest(const TTest&)”
*静态_cast(NULL));
如果该方法返回std::unique_ptr
,则错误相同,因为std::unique_ptr
也删除了复制ctor
因此,我的问题是:如何模拟这些返回带有已删除副本的对象的方法
我正在使用googletestv1.7、GCC 5.3.0和Ubuntu 14.04.1。正如在评论中提到的,Google Test 1.8似乎支持模拟这些功能() 至于1.7,我找到了一个解决方案 首先,创建一个实用程序类来包装不可复制的对象:
template <typename T>
class Mover
{
public:
Mover(T&& object)
: object(std::move(object)),
valid(true)
{
}
Mover(const Mover<T>& other)
: object(const_cast<T&&>(other.object)),
valid(true)
{
assert(other.valid);
other.valid = false;
}
Mover& operator=(const Mover& other)
{
assert(other.valid);
object = const_cast<T&&>(other.object);
other.valid = false;
valid = true;
}
T& get()
{
assert(valid);
return object;
}
const T& get() const
{
assert(valid);
return *object;
}
private:
T object;
mutable bool valid;
};
template <typename T>
inline Mover<T> Movable(T&& object)
{
return Mover<T>(std::move(object));
}
模板
班级搬运工
{
公众:
移动器(T&对象)
:对象(标准::移动(对象)),
有效(真)
{
}
移动器(固定移动器和其他)
:object(const_cast(other.object)),
有效(真)
{
断言(其他有效);
other.valid=false;
}
移动器和操作员=(常量移动器和其他)
{
断言(其他有效);
object=const_cast(other.object);
other.valid=false;
有效=真;
}
T&get()
{
断言(有效);
返回对象;
}
常量T&get()常量
{
断言(有效);
返回*对象;
}
私人:
T对象;
可变布尔有效;
};
模板
内联移动器(T&&object)
{
返回移动器(std::move(object));
}
然后创建一个代理模拟:
class MockMyInterface : public MyInterface
{
public:
MOCK_METHOD0(GetUniqueTest_, Mover<TTest>());
TTest GetUniqueTest()
{
return std::move(GetUniqueTest_().get());
}
}
class MockMyInterface:公共MyInterface
{
公众:
MOCK_方法0(GetUniqueTest_,Mover());
测试GetUniqueTest()
{
返回std::move(GetUniqueTest_uz().get());
}
}
在这里回答我自己的问题只是为了提供最新信息
在googletest1.8.0版或更高版本中,它引入了ByMove(…)
,并且本机仅支持返回移动类型
因此,代码编译正常:
class MockMyInterface: public MyInterface{
public:
MOCK_METHOD0(GetUniqueTest, TTest());
}
但在运行时它抛出异常,因为gmock不知道如何返回默认值TTest
:
C++ exception with description "Uninteresting mock function call - returning default value.
Function call: GetUniqueTest()
The mock function has no default action set, and its return type has no default value set." thrown in the test body.
这可以通过在模拟类中设置默认操作轻松解决:
ON_CALL(*this, GetUniqueTest()).WillByDefault(Return(ByMove(TTest(0))));
注意:对于std::unique_ptr
,它没有问题,因为它有默认构造函数,默认情况下会返回nullptr
unique_ptr
综上所述,如果使用googletest1.8.0或更高版本,我们可以:
// My interface to mock
class MyInterface
{
public:
virtual ~MyInterface() {}
virtual TTest GetUniqueTest() = 0;
virtual std::unique_ptr<int> GetUniqueInt() = 0;
};
// The mock
class MockMyInterface: public MyInterface{
public:
MOCK_METHOD0(GetUniqueTest, TTest());
MOCK_METHOD0(GetUniqueInt, std::unique_ptr<int>());
MockMyInterface() {
ON_CALL(*this, GetUniqueTest())
.WillByDefault(Return(ByMove(TTest(0))));
}
};
//我的模拟接口
类MyInterface
{
公众:
虚拟~MyInterface(){}
虚拟测试GetUniqueTest()=0;
虚拟std::unique_ptr GetUniqueInt()=0;
};
//嘲弄
类MockMyInterface:公共MyInterface{
公众:
MOCK_方法0(GetUniqueTest,TTest());
MOCK_METHOD0(GetUniqueInt,std::unique_ptr());
MockMyInterface(){
调用时(*this,GetUniqueTest())
.WillByDefault(返回(ByMove(TTest(0)));
}
};
参考:[使用仅移动类型的模拟方法]
()我觉得google test 1.8似乎支持模拟这些功能:更新到google test 1.8可能是个好主意。@我的是的,我后来也发现了,但没有时间验证:)也许当你确认后,你也可以自行回答;)我还没有核实,但我相信这份文件。不管怎样,我的问题指定gtest版本是1.7,它还没有这种支持。是的,我验证了1.8.0版本支持仅移动类型。如果我们希望返回TTest(1)呢。WillByDefault(返回(ByMove(TTest(1)));然后返回1,对吗?
// My interface to mock
class MyInterface
{
public:
virtual ~MyInterface() {}
virtual TTest GetUniqueTest() = 0;
virtual std::unique_ptr<int> GetUniqueInt() = 0;
};
// The mock
class MockMyInterface: public MyInterface{
public:
MOCK_METHOD0(GetUniqueTest, TTest());
MOCK_METHOD0(GetUniqueInt, std::unique_ptr<int>());
MockMyInterface() {
ON_CALL(*this, GetUniqueTest())
.WillByDefault(Return(ByMove(TTest(0))));
}
};