80

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 ...)
curious_beast
  • 85
  • 1
  • 9
Nicoretti
  • 1,067
  • 1
  • 8
  • 9

6 Answers6

76

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.

VladLosev
  • 7,296
  • 2
  • 35
  • 46
  • Why isn't `mock.Sign(10, p)` also matched against `EXPECT_CALL(mock, Sign(Gt(0), _).WillRepeatedly(Return(1));`? If it is what are the priority rules? – pooya13 Jan 28 '19 at 18:16
  • 2
    Yep, expectations defined later override the preceding expectations for matching calls, as explained in https://github.com/google/googletest/blob/master/googlemock/docs/ForDummies.md#using-multiple-expectations. – VladLosev Jan 30 '19 at 18:48
19
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);
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • But it seems that when I try to override the default action previously defined with an EXPECT_CALL with an ON_CALL it does not work. Any idea? – Nicoretti Dec 18 '12 at 14:58
  • 2
    @Nicoretti No, it does not work. I am not even sure what would happen if you set both. Maybe in that case only one gets executed. BTW the gtest has a [section](http://code.google.com/p/googlemock/wiki/CheatSheet#Setting_Default_Actions) explaining how to set a default behaviour. – BЈовић Dec 18 '12 at 21:14
  • 1
    yeah saw this one but I was curious and confused because of the fact that EXPECT_CALL can be used to modify the default behaviour. And the docs don't say anything about the side effects/priority ... when using both of them. – Nicoretti Dec 19 '12 at 08:30
8

Here is the "official" explanation about the most important differences between ON_CALL and EXPECT_CALL as explained in the gMock Cookbook.

There are basically two constructs for defining the behavior of a mock object: ON_CALL and EXPECT_CALL.

The difference?

ON_CALL defines what happens when a mock method is called, but doesn't imply any expectation on the method being called.

EXPECT_CALL not only defines the behavior, but also sets an expectation that the method must be called with the given arguments, for the given number of times (and in the given order when you specify the order too).

Since EXPECT_CALL does more, isn't it better than ON_CALL?

Not really. Every EXPECT_CALL adds a constraint on the behavior of the code under test. Having more constraints than necessary is bad - even worse than not having enough constraints.

This may be counter-intuitive. How could tests that verify more be worse than tests that verify less? Isn't verification the whole point of tests?

The answer, lies in what a test should verify. A good test verifies the contract of the code. If a test over-specifies, it doesn't leave enough freedom to the implementation. As a result, changing the implementation without breaking the contract (e.g. refactoring and optimization), which should be perfectly fine to do, can break such tests. Then you have to spend time fixing them, only to see them broken again the next time the implementation is changed.

Keep in mind that one doesn't have to verify more than one property in one test. In fact, it's a good style to verify only one thing in one test. If you do that, a bug will likely break only one or two tests instead of dozens (which case would you rather debug?). If you are also in the habit of giving tests descriptive names that tell what they verify, you can often easily guess what's wrong just from the test log itself.

So use ON_CALL by default, and only use EXPECT_CALL when you actually intend to verify that the call is made.

Nadim Z
  • 91
  • 1
  • 6
2

One difference is that the ON_CALL behavior (default behavior) and the EXPECT_CALL expectations are cleared differently.

https://github.com/google/googletest/blob/master/googlemock/docs/cheat_sheet.md#verifying-and-resetting-a-mock

using ::testing::Mock;
...
// Verifies and removes the expectations on mock_obj;
// returns true if and only if successful.
Mock::VerifyAndClearExpectations(&mock_obj);
...
// Verifies and removes the expectations on mock_obj;
// also removes the default actions set by ON_CALL();
// returns true if and only if successful.
Mock::VerifyAndClear(&mock_obj);

This can be used to clear expectations at some point in your test, but still keep the default behavior of the mock object. Notice that this is not the case for StrictMock objects since they will not allow the test to pass without actual expectations, even with a defined default behavior setup with ON_CALL.

Martin G
  • 17,357
  • 9
  • 82
  • 98
1

See here https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall

There are basically two constructs for defining the behavior of a mock object: ON_CALL and EXPECT_CALL. The difference? ON_CALL defines what happens when a mock method is called, but doesn't imply any expectation on the method being called. EXPECT_CALL not only defines the behavior, but also sets an expectation that the method will be called with the given arguments, for the given number of times (and in the given order when you specify the order too).

rrosa
  • 368
  • 4
  • 9
kula85
  • 73
  • 1
  • 9
0

I am puzzled that no answer mentioned the most important term: Uninteresting call.

EXPECT_CALL signals, that the function call is relevant/interesting. If the the expected function call will not match your specification (number of times called, arguments, ...), then this is a failed expectation which leads to a failed test case.

If an ON_CALL is used without any further EXPECT_CALL on the respective funtion, then this signals that the function is "uninteresting", and the further behaviour vastly depends on the type of mock that we use (strict/naggy/nice), which ranges from ignoring the call to failing the test case.

Use EXPECT_CALL for what is essential for your test purpose, use ON_CALL for specifying actions that you need in order to navigate through your code-under-test, and, if not specifically required, avoid over-specification by skipping EXPECT_CALL as well as ON_CALL for non-relevant functions (and use the GMock-defined default behaviour).

Dan
  • 61
  • 12