如果一个接口有一个函数来创建一个删除了copy-ctor的对象,那么如何模拟这个函数呢? Gmock似乎在内部使用了对象的复制构造函数。
E.g。
// 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>
也删除了copy-ctor。
所以我的问题是:如何模拟返回删除了copy-ctors的对象的方法?
我使用googletest v1.7 ,GCC 5.3.0和Ubuntu 14.04.1。
答案 0 :(得分:6)
在这里回答我自己的问题只是为了提供更新的信息。
使用googletest 版本1.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.
通过在mock类中设置默认操作,可以轻松解决此问题:
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))));
}
};
答案 1 :(得分:4)
正如Mine的评论中所提到的,Google Test 1.8似乎支持模拟此类函数(documentation)。
至于1.7我找到了解决方案here。
首先,创建一个实用程序类来包装不可复制的对象:
<asp:TextBox ID="txtarea" runat="server" Width="700px" Height="80px" TextMode="MultiLine" onkeyup="cnt()" MaxLength="1000"></asp:TextBox>
<p style="text-align: right;">
<asp:Label ID="lblcharcnt" runat="server" Text="1000"></asp:Label>
</p>
<asp:Label ID="lblcount" runat="server" Text='<%#Eval("row") %>' Visible="false"></asp:Label>
</ItemTemplate>
</asp:Repeater>
<script type="text/javascript">
function cnt() {
var a = document.getElementById("txtarea").value;
document.getElementById("lblcharcnt").innerHTML = 15 - a.length;
}
</script>
然后创建一个proxy-mock:
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));
}