Google Mock: multiple expectations on same function with different parameters
Asked Answered
R

2

9

Consider the case where a certain mocked function is expected to be called several times, each time with a different value in a certain parameter. I would like to validate that the function was indeed called once and only once per value in a certain list of values (e.g. 1,2,5).

On the other hand, I would like to refrain from defining a sequence as that would dictate a certain order, which is an implementation detail I would like to keep free.

Is there some kind of matcher, or other solution for this case?

I'm not sure if this influences the solution in any way but I do intend to use WillOnce(Return(x)) with a different x per value in the list above.

Rondi answered 21/4, 2011 at 11:5 Comment(1)
Related: stackoverflow.com/questions/44034633/…Liverwurst
A
14

By default gMock expectations can be satisfied in any order (precisely for the reason you mention -- so you don't over specify your tests).

In your case, you just want something like:

EXPECT_CALL(foo, DoThis(1));
EXPECT_CALL(foo, DoThis(2));
EXPECT_CALL(foo, DoThis(5));

And something like:

foo.DoThis(5);
foo.DoThis(1);
foo.DoThis(2);

Would satisfy those expectations.

(Aside: If you did want to constrain the order, you should use InSequence: https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#expecting-ordered-calls-orderedcalls)

Atilt answered 5/5, 2011 at 15:3 Comment(3)
I must have been tiered when writing that question. I'll leave it posted for all those other tiered programmers :)Rondi
Can't the EXPECT_CALL be more compact? Something like: EXPECT_CALL(foo, DoThis(Args<1, 2, 5>)); ?Bristling
@xwl, no. Remember that EXPECT_CALL() is a macro, and macro expansion is difficult enough as it is. I suspect what you are showing there would be impossible to implement via a macro.Liverwurst
T
3

If you expect a function, DoThing, to be called with many different parameters, you can use the following pattern:

for (auto const param : {1, 2, 3, 7, -1, 2}){
    EXPECT_CALL(foo, DoThing(param));
}

This is particularly helpful if your EXPECT_CALL includes many parameters, of which only one is changing, or if your EXPECT_CALL includes many Actions to be repeated.

Tobin answered 24/1, 2018 at 16:18 Comment(4)
EXPECT_CALL() is a macro which expands in place. I'm pretty sure this will not work, as it creates one macro expansion instead of 6 unique macro expansions. Have you tested it to conclusively prove it works?Liverwurst
@GabrielStaples yes, I've tested this many times. It's not relevant that EXPECT_CALL is a macro, or that the macro is only expanded once. For example, you can have a helper function that sets expectations based on parameters provided to that function. You can call that function as many times as you want. Gtest/Gmock does a good job of making copies of everything you pass into matchers and expectations.Tobin
Thanks. Makes sense. I've upvoted it. Haven't tested it myself, but if it works it looks very useful.Liverwurst
I use this pattern a lot, but a negative is that the output will reference "EXPECT_CALL(foo, DoThing(param));", i.e. "param" will not be expanded to indicate which param actually fails. You have to balance up the code saved versus the convenience of seeing what caused the failure.Cranford

© 2022 - 2024 — McMap. All rights reserved.