I have a factory that returns a smart pointer. Regardless of what smart pointer I use, I can't get Google Mock to mock the factory method.
The mock object is the implementation of a pure abstract interface where all methods are virtual. I have a prototype:
MOCK_METHOD0(Create, std::unique_ptr<IMyObjectThing>());
And I get:
"...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>'"
The type pointed to in the smart pointer is defined.
And I get it's trying to access one of the constructors declared private, but I don't understand why. When this was an std::auto_ptr, the error said there was no copy constructor, which confuses me.
Anyway, is there a way to Mock a method that returns a smart pointer? Or is there a better way to build a factory? Is my only resolve to return a raw pointer (blech...)?
My environment is Visual Studio 2010 Ultimate and Windows 7. I'm not using CLI.
One of the advantages of smart pointers is, that they ensure due to RAII, that the actual object is deleted. When using a raw pointer, you need to have a delete for every possible exit point, and still an exception will lead to a memory leak. Smart pointers will also free the memory if an exception occurs.
Smart pointers are used to make sure that an object is deleted if it is no longer used (referenced). The unique_ptr<> template holds a pointer to an object and deletes this object when the unique_ptr<> object is deleted.
A Smart Pointer is a wrapper class over a pointer with an operator like * and -> overloaded. The objects of the smart pointer class look like normal pointers. But, unlike Normal Pointers it can deallocate and free destroyed object memory.
A feasible workaround for google mock framework's problems with non (const) copyable function arguments and retun values is to use proxy mock methods.
Suppose you have the following interface definition (if it's good style to use std::unique_ptr
in this way seems to be more or less a philosophical question, I personally like it to enforce transfer of ownership):
class IFooInterface { public: virtual void nonCopyableParam(std::unique_ptr<IMyObjectThing> uPtr) = 0; virtual std::unique_ptr<IMyObjectThing> nonCopyableReturn() = 0; virtual ~IFooInterface() {} };
The appropriate mock class could be defined like this:
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* ()); };
You just need to take care, that configurations (Actions taken) for the nonCopyableReturnProxy()
method return either NULL
or an instance allocated dynamically on the heap.
There's a google-mock user forum thread discussing this topic where one of the maintainers states that the google-mock framework won't be changed to support this in future arguing that their policies strongly discourage the usage std::auto_ptr
parameters. As mentioned this is IMHO a philosophical point of view, and the capabilities of the mocking framework shouldn't steer what kind of interfaces you want to design or you can use from 3rd party APIs.
As said the answer describes a feasible workaround.
I know this post was from a long time ago, so you've probably discovered the answer by now.
gmock previously did not support mock functions that returned any movable type, including smart pointers. However, in April 2017, gmock introduced a new Action modifier ByMove
.
EXPECT_CALL(*foo_, Bar(_, )).WillOnce(Return(ByMove(some_move_only_object)));
where some_move_only_object can be e.g. a std::unique_ptr.
So yes, now gmock can mock a function that takes a smart pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With