Search code examples
c++googletestgooglemock

Returning multiple unique_ptr from factory mock


How can I return multiple object from a mocked factory returning unique_ptr, when the calls cannot be identified through different input parameters to the called function?

I'm doing this:

EXPECT_CALL(MyFactoryMock, create())
  .WillRepeatedly(Return(ByMove(std::make_unique<MyObjectTypeMock>())));

And run-time error is:

[ FATAL ] /.../tools/googletest/1.8.0-57/include/gmock/gmock-actions.h:604:: Condition !performed_ failed. A ByMove() action should only be performed once.

Doing the same thing only once, using WillOnce, works fine.

Follow-up question: Return multiple mock objects from a mocked factory function which returns std::unique_ptr


Solution

  • ByMove is designed to move a predefined value that you prepared in your test, so it can only be called once. If you need something else, you'll need to write it yourself explicitly.

    Here's an excerpt from the googletest documentation:

    Quiz time! What do you think will happen if a Return(ByMove(...)) action is performed more than once (e.g. you write ... .WillRepeatedly(Return(ByMove(...)));)? Come think of it, after the first time the action runs, the source value will be consumed (since it’s a move-only value), so the next time around, there’s no value to move from – you’ll get a run-time error that Return(ByMove(...)) can only be run once.

    If you need your mock method to do more than just moving a pre-defined value, remember that you can always use a lambda or a callable object, which can do pretty much anything you want:

      EXPECT_CALL(mock_buzzer_, MakeBuzz("x"))
          .WillRepeatedly([](StringPiece text) {
            return MakeUnique<Buzz>(AccessLevel::kInternal);
          });
    
      EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));  
      EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));
    

    Every time this EXPECT_CALL fires, a new unique_ptr<Buzz> will be created and returned. You cannot do this with Return(ByMove(...)).