如果一个接口有一个函数来创建一个带有已删除复制器的对象,那么如何模拟这个函数呢?Gmock似乎在内部使用对象的复制构造函数。
例如。
// The object with deleted copy-ctor and copy-assignment
class TTest
{
public:
TTest() = delete;
TTest(const TTest&) = delete;
TTest& operator=(const TTest&) = delete;
TTest(TTest&&) = default;
TTest& operator=(TTest&&) = default;
explicit TTest(int) {
}
};
// My interface to mock
class MyInterface
{
public:
virtual ~MyInterface() {}
virtual TTest GetUniqueTest() = 0;
};
// The mock
class MockMyInterface: public MyInterface{
public:
MOCK_METHOD0(GetUniqueTest, TTest());
}编译错误显示:
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));如果方法返回std::unique_ptr<T>,由于std::unique_ptr<T>也删除了复制-ctor,所以错误是相同的。
因此,我的问题是:如何模拟那些使用已删除的复制函数返回对象的方法?
我使用的是googletest v1.7、GCC 5.3.0和Ubuntu14.04.1。
发布于 2017-02-28 10:24:23
正如我的的评论中所提到的,GoogleTest1.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));
}然后创建一个代理模拟:
class MockMyInterface : public MyInterface
{
public:
MOCK_METHOD0(GetUniqueTest_, Mover<TTest>());
TTest GetUniqueTest()
{
return std::move(GetUniqueTest_().get());
}
}发布于 2017-03-01 09:40:14
在这里回答我自己的问题,只是为了提供最新的信息。
使用googletest 发行版1.8.0或更高版本,它引入了ByMove(...)并支持本地只返回移动类型。
所以代码编译OK:
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<T>,因为它有默认构造函数,因此默认情况下返回nullptr unique_ptr。
因此,如果使用googletest 1.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))));
}
};参考资料:模拟使用仅移动类型的方法。
https://stackoverflow.com/questions/42505119
复制相似问题