eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.26k stars 175 forks source link

Functionality to reset invocations #15

Closed sleep-deprived closed 9 years ago

sleep-deprived commented 9 years ago

Hi,

First let me start by saying that this is a great framework. I ran across it a few hours ago and already I was able to use it in a few unit tests, eliminating some self made mocking classes. It also seems really robust and feature-rich.

I would like to propose / request a few features. I'll open a separate issue for each.

For this request, there might already be an implemented solution, but I couldn't find it. I also seem to not fully understand the conditions in which Verify() fails - since the order of calls to the various Verify*() macros matters.

We have a few unit tests each representing a flow. I want to be able to check the invocation of methods in my mocks after every step of the flow.

I use the Verify().Once() to make sure the correct method and parameters were called, and immediately VerifyNoOtherInvocations(mock) to make sure nothing else was called.

What I'd like to do then is to 'clear the table' for the next step, so I can once again call Once() (with different parameters, if needed) and VerifyNoOtherInvocations().

Doing just that seems to work, unless the same parameters repeat themselves, in which case Verify().Once() complains that the method was called more than once. I'd like to avoid the need for counting the calls by myself, especially since adding a step in the middle of the flow might require me to change everything.

What I suggest is a syntax such as: Method(mock, methodName).ResetInvocations()

This will cause the internal structs to delete all the previously recorded invocations.

Do you have another solution? Or if not, is it possible to add it for the next version?

Thanks.

eranpeer commented 9 years ago

Hi, Fakeit doesn't support clearing only the recorded invocations. You can use mock.Reset() to completely reset the state of the mock to its initial state (as it was after ctor), but then you will have to re-stub the methods you're about to call.

I will add support for a clearing the recorded invocations in the next few days. Meantime here is what you can do:

struct AnInterface {
     virtual int func(int) = 0;
}; 
Mock<AnInterface> mock;
When(Method(mock, func)).AlwaysReturn(0);

AnInterface& obj = mock.get();

obj.func(1);
// Verify exactly one invocation of obj.func(1)
Verify(Method(mock, func).Using(1)).Once();

obj.func(2);
// Verify one invocation of obj.func(any argument) followed by obj.func(2)
 Verify(Method(mock, func) + Method(mock, func).Using(2)).Once();

obj.func(3);
// Verify 2 invocations of obj.func(any argument) followed by obj.func(3)
Verify(2 * Method(mock, func) + Method(mock, func).Using(3)).Once();

obj.func(4);
// Verify 3 invocations of obj.func(any argument) followed by obj.func(4)
Verify(3 * Method(mock, func) + Method(mock, func).Using(4)).Once();

I hope this helps your situation.

eranpeer commented 9 years ago

Ok, I thought about an elegant solution for this one a lot. What we need here is to be able to use only the unverified invocations so only the new invocations will be used for verification. Here is my solution:

struct AnInterface {
     virtual int func(int) = 0;
}; 
Mock<AnInterface> mock;
When(Method(mock, func)).AlwaysReturn(0);

AnInterface& obj = mock.get();

obj.func(1);
Unverified.Verify(Method(mock, func)).Once();

obj.func(1);
Unverified.Verify(Method(mock, func)).Once();

obj.func(2);
obj.func(3);

Unverified.Verify(2 * Method(mock, func));

All you need to do is to add the "Unverified" prefix to specify that you want to include only the new invocation that where not verified until now.

Thanks for sending this enhancement request. FakeIt is better now.

sleep-deprived commented 9 years ago

It seems that using this somehow resets the relevant stub when the method parameters called are changed.

If I set a stub (with When and Using(_)), I then call Unverified.Verify() on that method - as long as the parameters are the same it's OK, but once I call it with different parameters I get the error:

Unexpected method invocation: unknown()

If I call When() again before this call it works.

thanks

eranpeer commented 9 years ago

I'm not sure I understand the problem. Can you please send a short example that reproduces it. Thanks. On Apr 6, 2015 2:32 PM, "sleep-deprived" notifications@github.com wrote:

It seems that using this somehow resets the relevant stub when the method parameters called are changed.

If I set a stub (with When and Using(_)), I then call Unverified.Verify() on that method - as long as the parameters are the same it's OK, but once I call it with different parameters I get the error:

Unexpected method invocation: unknown()

If I call When() again before this call it works.

thanks

— Reply to this email directly or view it on GitHub https://github.com/eranpeer/FakeIt/issues/15#issuecomment-90023734.

eranpeer commented 9 years ago

You should get an "Unexpected method invocation: unknown()" error when calling a method that was not stubbed. If you get it in any other situation please send a short example. Thanks,

On Mon, Apr 6, 2015 at 2:56 PM, Eran Pe'er eranpe@gmail.com wrote:

I'm not sure I understand the problem. Can you please send a short example that reproduces it. Thanks. On Apr 6, 2015 2:32 PM, "sleep-deprived" notifications@github.com wrote:

It seems that using this somehow resets the relevant stub when the method parameters called are changed.

If I set a stub (with When and Using(_)), I then call Unverified.Verify() on that method - as long as the parameters are the same it's OK, but once I call it with different parameters I get the error:

Unexpected method invocation: unknown()

If I call When() again before this call it works.

thanks

— Reply to this email directly or view it on GitHub https://github.com/eranpeer/FakeIt/issues/15#issuecomment-90023734.

Eran 972-52-8387550

eranpeer commented 9 years ago

The error message should be followed by one of:

  1. "Could not find Any recorded behavior to support this method call."
  2. "An unmocked method was invoked. All used virtual methods must be stubbed!"

Which message did you see?

On Mon, Apr 6, 2015 at 7:42 PM, Eran Pe'er eranpe@gmail.com wrote:

You should get an "Unexpected method invocation: unknown()" error when calling a method that was not stubbed. If you get it in any other situation please send a short example. Thanks,

On Mon, Apr 6, 2015 at 2:56 PM, Eran Pe'er eranpe@gmail.com wrote:

I'm not sure I understand the problem. Can you please send a short example that reproduces it. Thanks. On Apr 6, 2015 2:32 PM, "sleep-deprived" notifications@github.com wrote:

It seems that using this somehow resets the relevant stub when the method parameters called are changed.

If I set a stub (with When and Using(_)), I then call Unverified.Verify() on that method - as long as the parameters are the same it's OK, but once I call it with different parameters I get the error:

Unexpected method invocation: unknown()

If I call When() again before this call it works.

thanks

— Reply to this email directly or view it on GitHub https://github.com/eranpeer/FakeIt/issues/15#issuecomment-90023734.

Eran 972-52-8387550

Eran 972-52-8387550