Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gmock setting default actions / ON_CALL vs. EXPECT_CALL

Tags:

c++

googlemock

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 ...)
like image 767
Nicoretti Avatar asked Dec 18 '12 12:12

Nicoretti


People also ask

Is Gmock included in GTest?

gMock is bundled with googletest.

How do you mock a function in C++?

It's possible to use Google Mock to mock a free function (i.e. a C-style function or a static method). You just need to rewrite your code to use an interface (abstract class). public: ... virtual bool Open(const char* path, const char* mode) { return OpenFile(path, mode); } };

What is SetArgReferee?

SetArgReferee<N>(value) Assign value to the variable referenced by the N -th (0-based) argument. SetArgPointee<N>(value) Assign value to the variable pointed by the N -th (0-based) argument.


2 Answers

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.

like image 56
VladLosev Avatar answered Sep 22 '22 16:09

VladLosev


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

As you said, these two lines are doing exactly the same thing, therefore there are no differences at all. Use either way to set a default action as you please.

However, there is a logical difference :

  • ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01)); means that the method might be called, and if that happens, every call will return 0x01
  • EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01)); means that it is expected that the method will be called, and every call will return 0x01

By the way, there is a Setting default actions in their cheat sheet, which says :

To customize the default action for a particular method, use ON_CALL():

ON_CALL(mock_object, method(matchers))     .With(multi_argument_matcher)  ?     .WillByDefault(action); 
like image 25
BЈовић Avatar answered Sep 18 '22 16:09

BЈовић