Googletest: Add support for move only parameters in mocked methods

Created on 28 Jul 2015  路  18Comments  路  Source: google/googletest

The new C++11 standard allows for rvalue references in method parameters. Using 
those for move semantics is very useful. We need to suppor them, e.g.:

MOCK_METHOD1(mock, foo(int&& i));

Original issue reported on code.google.com by vladlosev on 19 Dec 2011 at 12:45

Priority-Medium Type-Enhancement auto-migrated

Most helpful comment

Is there anything preventing this from being integrated as a pull request (or maybe it already is and just isn't linked)? This seems like a fairly useful feature to have, and from experience I can say its extremely annoying to have to work around, especially when it gets in the way of being able to use auto-generated mocks. If nobody else has something in the works, I'd be happy to try and bring it together (though maybe the original authour of the patch might want to have a go?).

All 18 comments

There are also techniques for doing this in C++98/03 *without* using rvalue 
references.

In particular, look at Howard Hinnant's unique_ptr<> emulation: 
http://home.roadrunner.com/~hinnant/unique_ptr03.html

What this means it that people can write APIs in C++98 of this style:

// This is pass-by-value not rvalue-reference.
void TakesOwnership(unique_ptr<Foo> f);

You can only call this with an rvalue argument since unique_ptr is move-only.  
With gmock, this presents a problem that is separate from supporting APIs that 
take rvalue-references.

Original comment by [email protected] on 19 Dec 2011 at 7:44

Is there a status on this? Google mocks seems to be the most promising C++ 
mocking framework, and it's suggested by my company. The first time I tried 
using gmock, though, my interface uses std::unique_ptr and my gmock'ed class is 
not compiling correctly.

Original comment by [email protected] on 1 Mar 2013 at 2:31

I have similar problems. I would dearly love to use gmock but being unable to 
return move-only types is a non-starter in today's C++.

Original comment by [email protected] on 16 Aug 2013 at 2:29

It's reasonably straightforward to add a wrapping function whenever you require 
a move-supporting mock:

struct mock {
   void insert( unique_ptr<int> p ) {
      insert_(p);
   }

   MOCK_METHOD1( insert_, void(unique_ptr<int>&) );
};

When the unit under test calls e.g. insert( std::move( some_ptr )) the wrapper 
accepts the move-only parameter, then passes it by reference to the mock itself.
If your mock needs to move the value further then it can, as you can 
std::move() from a non-const lvalue reference type.

It may be worth questioning whether enforcing the move-only interface on your 
mock is beneficial. If instead of adding a move-enabled wrapper around the mock 
method you were to just make your mock method accept lvalue references, you can 
still verify the value of the parameter, move it, or whatever, without loss of 
test completeness.

The only downside I see is that by dropping the requirement that the parameter 
be moved in, your unit under test might forget to do that in some place. Since 
this would generate a compilation error when you build it with the real 
instance of whatever you are mocking, this doesn't really lose you anything 
though. Hope that makes sense...

@vladlosev - this is the googletest project, but you're requesting a change to 
googlemock. It may be better to post your request to the googlemock project 
page...

Original comment by [email protected] on 21 Aug 2013 at 10:29

What about returning types that dont have copy constructor/operator but have 
move constructor/operator? E.g.: std::unique_ptr.


Original comment by [email protected] on 8 Jul 2014 at 9:01

Returning move-only types in mock methods is supported.
The 'Return()' action does not have the support yet, but it can be done with 
'Invoke()' or 'DefaultValue<T>::SetFactory()'

Original comment by [email protected] on 8 Jul 2014 at 7:56

Here is a patch we use.
It supports move-only parameters except in DoAll(), but that doesn't even make 
sense with non-copyable objects.
It contains a few other fixes as well.

It works if applied to r485 version, but all pumped sources must be regenerated 
after applying the patch.

I'm not sure if it works with non-C++11 compilers.
I tested it with Visual Studio 2013, gcc 4.8, 4.9, clang 3.4, 3.5

Original comment by [email protected] on 20 Nov 2014 at 4:13

Attachments:

In the previous comment the r485 link incorrectly points to the GoogleTest 
revision, I meant the GoogleMock revision.

Original comment by [email protected] on 20 Nov 2014 at 4:14

Is there any progress on this issue? I am forced to either change my API or not test this part of my code, which both to me are very undesirable.

@timdave13 the patch in https://github.com/google/googletest/issues/395#issuecomment-125645954 worked fine for me.

Thanks @lacombar. I was hoping to stay with master so as to not have to manage another vendor branch. It is a bit more complicated for us since we use svn, but not terrible.

Is there anything preventing this from being integrated as a pull request (or maybe it already is and just isn't linked)? This seems like a fairly useful feature to have, and from experience I can say its extremely annoying to have to work around, especially when it gets in the way of being able to use auto-generated mocks. If nobody else has something in the works, I'd be happy to try and bring it together (though maybe the original authour of the patch might want to have a go?).

@BillyDonahue: anything we can do to get this merged?

There's not a PR here. We do have to be a little careful about adding C++11 features.

related to #1155 - maybe fix provided #914

I have been cleaning up older and inactive GitHub googletest issues. You may see an issue "closed" if it appears to be inactive/abandoned
Thank you

For people finding this issue through search engines: There is support for rvalue references for a limited subset of gmocks actions along those lines:

EXPECT_CALL(mock, MakeUnique()).WillOnce(Return(ByMove(std::move(i))));

Is MOCK_METHOD1(mock, foo(int&& i)); supported yet?

Edit: For anyone wondering move only argument types are supported with some caveats.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robindegen picture robindegen  路  4Comments

Joebeazelman picture Joebeazelman  路  5Comments

cyberdecker picture cyberdecker  路  3Comments

marknelson picture marknelson  路  4Comments

ebioman picture ebioman  路  3Comments