Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

google mock - how to say "function must be called ONCE with a certain parameter but ok to be called many times with different parameters"?

I need to detect that a given function has been called exactly ONCE with a certain set of arguments.

EXPECT_CALL(Mock_Obj, func("abc")).Times(1)

but it's ok for that function to be called with different arguments any number of times.

How do I express that?

like image 666
Bob Avatar asked May 29 '17 19:05

Bob


2 Answers

In Google Mock, later expectations override earlier ones (more details in the docs), so you can write this:

EXPECT_CALL(Mock_Obj, func(_)).Times(AnyNumber());
EXPECT_CALL(Mock_Obj, func("abc")).Times(1);
like image 121
VladLosev Avatar answered Nov 16 '22 04:11

VladLosev


Here is a little more info. Do like VladLosev said. Put the default (most generic because it allows any argument with the _ character) case first and the more specific cases after, to override the default case if they match first. I say that the latter EXPECT_CALL()s may match first because gmock does a reverse search for matches, meaning it tries to match the last EXPECT_CALL() first, then it moves its way upwards, stopping and exiting this process at the first match it finds for the call, in this reverse order.

EXPECT_CALL(Mock_Obj, func(_)).Times(AnyNumber());
EXPECT_CALL(Mock_Obj, func("abc")).Times(1);
EXPECT_CALL(Mock_Obj, func("def")).Times(1);
EXPECT_CALL(Mock_Obj, func("cab")).Times(1);
EXPECT_CALL(Mock_Obj, func("bac")).Times(1);

From the "gMock for Dummies {#GMockForDummies}" guide:

Using Multiple Expectations {#MultiExpectations}

So far we've only shown examples where you have a single expectation. More realistically, you'll specify expectations on multiple mock methods which may be from multiple mock objects.

By default, when a mock method is invoked, gMock will search the expectations in the reverse order they are defined, and stop when an active expectation that matches the arguments is found (you can think of it as "newer rules override older ones."). If the matching expectation cannot take any more calls, you will get an upper-bound-violated failure. Here's an example:

using ::testing::_;
...
EXPECT_CALL(turtle, Forward(_));  // #1
EXPECT_CALL(turtle, Forward(10))  // #2
    .Times(2);

If Forward(10) is called three times in a row, the third time it will be an error, as the last matching expectation (#2) has been saturated. If, however, the third Forward(10) call is replaced by Forward(20), then it would be OK, as now #1 will be the matching expectation.

Note: Why does gMock search for a match in the reverse order of the expectations? The reason is that this allows a user to set up the default expectations in a mock object's constructor or the test fixture's set-up phase and then customize the mock by writing more specific expectations in the test body. So, if you have two expectations on the same method, you want to put the one with more specific matchers after the other, or the more specific rule would be shadowed by the more general one that comes after it.

Tip: It is very common to start with a catch-all expectation for a method and Times(AnyNumber()) (omitting arguments, or with _ for all arguments, if overloaded). This makes any calls to the method expected. This is not necessary for methods that are not mentioned at all (these are "uninteresting"), but is useful for methods that have some expectations, but for which other calls are ok. See Understanding Uninteresting vs Unexpected Calls.

Related:

  1. google mock - can I call EXPECT_CALL multiple times on same mock object?
like image 27
Gabriel Staples Avatar answered Nov 16 '22 02:11

Gabriel Staples