Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify consecutive returns in gmock?

Tags:

In Mockito we can specify multiple returns like (taken from here):

//you can set different behavior for consecutive method calls.
 //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls.
 when(mock.someMethod("some arg"))
  .thenReturn(new RuntimeException())
  .thenReturn("foo");

 //There is a shorter way of consecutive stubbing:
 when(mock.someMethod()).thenReturn(1,2,3);
 when(mock.otherMethod()).thenThrow(exc1, exc2);

Is there a way to specify multiple returns for a mock made with gmock? Currently I have:

store_mock_ = std::make_shared<StorageMock>();
ON_CALL(*store_mock_, getFileName(_)).Return("file1").Return("file2");

which doesn't compile because I can't figure out multiple returns in gmock. Is this possible with gmock? If not, is there another way to solve this problem? I've found that we can EXPECT multiple return values like:

using ::testing::Return;...
EXPECT_CALL(turtle, GetX())
    .WillOnce(Return(100))
    .WillOnce(Return(200))
    .WillOnce(Return(300));

However, I haven't found any docs for mocking multiple returns with ON_CALL.

like image 618
Paymahn Moghadasian Avatar asked Oct 26 '15 20:10

Paymahn Moghadasian


People also ask

How do you mock in gMock?

first, you use some simple macros to describe the interface you want to mock, and they will expand to the implementation of your mock class; next, you create some mock objects and specify its expectations and behavior using an intuitive syntax; then you exercise code that uses the mock objects.

What is expect call in gMock?

EXPECT_CALL sets expectation on a mock calls. Writing EXPECT_CALL(mock, methodX(_)). WillRepeatedly(do_action); tells gMock that methodX may be called on mock any number of times with any arguments, and when it is, mock will perform do_action .

What is Expect_call?

means it can be used at most once, while * means it can be used any number of times. In order to pass, EXPECT_CALL must be used before the calls are actually made.


2 Answers

ON_CALL is more used for setting default behavior of the function. I.e. you know that in tested code the mocked function is called, you want to set some default value, but it is not actually important how many times function is called.

The example:

  ON_CALL(foo, Sign(_))       .WillByDefault(Return(-1));   ON_CALL(foo, Sign(0))       .WillByDefault(Return(0));   ON_CALL(foo, Sign(Gt(0)))       .WillByDefault(Return(1)); 

To get your desired behavior I'd use expectations - you already provided some example in question, just to show more - an example when you expect 1, 2 then always 3:

  EXPECT_CALL(foo, Sign(_))       .WillOnce(Return(1))       .WillOnce(Return(2))       .WillRepeatedly(Return(3)); 

EXPECT_CALL "way" might be troublesome when you want to set this in test fixture SetUp - and some tests might call foo only once. But, of course, there are ways to "control" ON_CALL return value for subsequent calls - but you must do it with special actions - like getting result of some function - like in this example:

class IDummy { public:     virtual int foo() = 0; };  class DummyMock : public IDummy { public:     MOCK_METHOD0(foo, int()); }; using namespace ::testing; class DummyTestSuite : public Test { protected:     DummyMock dummy;     void SetUp() override     {         ON_CALL(dummy, foo())            .WillByDefault(                  InvokeWithoutArgs(this, &DummyTestSuite::IncrementDummy));     }     int dummyValue = 0;     int IncrementDummy()     {         return ++dummyValue;     }  };   TEST_F(DummyTestSuite, aaa) {     ASSERT_EQ(1, dummy.foo());     ASSERT_EQ(2, dummy.foo());     ASSERT_EQ(3, dummy.foo());  }  
like image 108
PiotrNycz Avatar answered Oct 06 '22 00:10

PiotrNycz


@PiotrNycz's answer is correct and the preferred solution.

An alternative approach via a lambda function may give you more flexibility:

uint32_t callCount = 0; ON_CALL(*turtle, GetX())     .WillByDefault(testing::Invoke(         [&callCount]() -> int {             return ++callCount * 100;         }     )); 
like image 28
Roland Ettinger Avatar answered Oct 05 '22 22:10

Roland Ettinger