3

I am trying to reference an out argument of the mocked method getData. My problem is that "ControlData" has no copy constructor because it got deleted. As far as I understand, "SetArgReferee" does create an intermediate object before passing it by reference.

MOCK_METHOD1(getData, void(ControlData& par_rcl_ControlData));

ControlData loc_data;

EXPECT_CALL(loc_cl_control, getData(_)).WillOnce(SetArgReferee<0>(loc_data));

I have tried to create an custom action such as:

ACTION_P(SetArgRef, obj) { arg0 = &obj; }

But unfortunately this does not compile either. How can I pass an object directly on the mocked method?

Quarra
  • 2,527
  • 1
  • 19
  • 27
Pepelee
  • 433
  • 3
  • 19
  • Possibly related or duplicate: [How to mock methods return object with deleted copy-ctor?](https://stackoverflow.com/q/42505119/2118271) – Chris Olsen Feb 11 '20 at 02:49

1 Answers1

2

Quoting form GoogleMock Cook Book:

SetArgPointee() conveniently makes an internal copy of the value you pass to it, removing the need to keep the value in scope and alive. The implication however is that the value must have a copy constructor and assignment operator.

Presumably the same applies to SetArgReferee. This means you need a custom action to move the object into that reference (without using copy constructor at any place).

Fortunately, later on there is a suggestion:

but how do we work with methods accepting move-only arguments? The answer is that they work normally, although some actions will not compile when any of method's arguments are move-only. You can always use Return, or a lambda or functor:

What you need is a lambda (or any function object) that will pass argument by move:

ControlData loc_data;

auto SetArgByMove = [&loc_data](auto& arg){arg = std::move(loc_data);};
EXPECT_CALL(loc_cl_control, getData(_)).WillOnce(Invoke(SetArgByMove));

This should compile and run without issues.


You could probably make a custom action as well, but not via ACTION_P macro - it also creates a copy of the object. You would have to write fully fledged action by creating a class that inherits from ActionInterface

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
  • How would you change this if you wanted to set say, the second argument by move? – Keith Johnson Nov 17 '21 at 20:11
  • @KeithJohnson `WillOnce(WithArg<1>(Invoke(SetArgByMove)))` ([see on godbolt](https://godbolt.org/z/MjWTxvnK8)). Or a lambda that takes all arguments of the function, whichever looks cleaner - I prefer to use GoogleMock inbuilts wherever possible, but that sometimes means a horrible chain of calls, and they are not easily refactorable. – Yksisarvinen Nov 17 '21 at 22:31