How to mock methods return object with deleted copy-ctor?
Answer my own question here just to provide updated information.
With googletest release 1.8.0 or above, it introduces ByMove(...)
and supports return move-only types natively.
So the code compiles OK:
class MockMyInterface: public MyInterface{
public:
MOCK_METHOD0(GetUniqueTest, TTest());
}
But in run time it throws exception because gmock does not know how to return default 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.
This can be easily workaround by setting a default action in the mock class:
ON_CALL(*this, GetUniqueTest()).WillByDefault(Return(ByMove(TTest(0))));
Note: For std::unique_ptr<T>
it's OK because it has default constructor, a nullptr
unique_ptr
is returned by default.
So putting all together, if using googletest 1.8.0 or above, we can do:
// 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))));
}
};
Reference: [Mocking Methods That Use Move-Only Types] (https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#mocking-methods-that-use-move-only-types)
As mentioned in the comments by Mine, Google Test 1.8 seems to support mocking such functions (documentation).
As for 1.7 I've found a solution here.
First, create an utility class to wrap non-copyable objects:
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));
}
and then create a proxy-mock:
class MockMyInterface : public MyInterface
{
public:
MOCK_METHOD0(GetUniqueTest_, Mover<TTest>());
TTest GetUniqueTest()
{
return std::move(GetUniqueTest_().get());
}
}