gmock setting default actions / ON_CALL vs. EXPECT_CALL

Nicoretti picture Nicoretti · Dec 18, 2012 · Viewed 91k times · Source

I don't understand the difference between ON_CALL and EXPECT_CALL when using it to specify the default action.

So far I noticed/learned there are two ways to adjust the default action of a mock:

ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));

or

EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));

Could someone explain to me:

  • The difference between the two methods
  • The ups and downs of each one
  • When is it appropriate to use them (what kind of setup ...)

Answer

VladLosev picture VladLosev · Dec 19, 2012

There are subtle but significant differences between the two statements. 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. On the other hand,

ON_CALL(mock, methodX(_)).WillByDefault(do_action);

tells gMock that whenever methodX is invoked on mock, it should perform do_action. That feature is helpful in a scenario where you have to write many expectations on your mock, and most/all of them have to specify the same action -- especially if it's complex. You can specify that action in ON_CALL, and then write EXPECT_CALLs without specifying the action explicitly. E.g.,

ON_CALL(mock, Sign(Eq(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is zero"), Return(0)));
ON_CALL(mock, Sign(Gt(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is positive"), Return(1)));
ON_CALL(mock, Sign(Lt(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is negative"), Return(-1)));

Now, if you have to write a lot of EXPECT_CALLs, you don't have to mock's specify the behavior every time:

EXPECT_CALL(mock, Sign(-4, _));
EXPECT_CALL(mock, Sign(0, _));
EXPECT_CALL(mock, Sign(1, _)).Times(2);
EXPECT_CALL(mock, Sign(2, _));
EXPECT_CALL(mock, Sign(3, _));
EXPECT_CALL(mock, Sign(5, _));

In another example, assuming Sign returns int, if you write

ON_CALL(mock, Sign(Gt(0), _)).WillByDefault(Return(1));
EXPECT_CALL(mock, Sign(10, _));

the call mock.Sign(10) will return 1 as ON_CALL provides default behavior for a call specified by EXPECT_CALL. But if you write

EXPECT_CALL(mock, Sign(Gt(0), _).WillRepeatedly(Return(1));
EXPECT_CALL(mock, Sign(10, _));

the invocation of mock.Sign(10, p) will return 0. It will be matched against the second expectation. That expectation specifies no explicit action and gMock will generate a default action for it. That default action is to return a default value of the return type, which is 0 for int. The first expectation will be totally ignored in this case.