FakeItEasy icon indicating copy to clipboard operation
FakeItEasy copied to clipboard

Add assertion similar to Moq's `VerifyNoOtherCalls`

Open ChristoWolf opened this issue 2 years ago • 7 comments

Hi!

Currently, there is no such assertion available, although it would be very useful for use cases where strict fakes would need complex setups. One could of course manually keep track of already asserted calls, but it would be great if e.g. the FakeManager or the fake itself kept track of those. That list could then be checked against the list of executed calls.

I have an idea how to implement this, but the stuff for that is not accessible from consumer code. Let me know if I can help out with this!

ChristoWolf avatar Sep 01 '23 09:09 ChristoWolf

Hi, @ChristoWolf. Thanks for your interest in FakeItEasy.

I'm having problems finding Moq's documentation for VerifyNoOtherCalls. Is the description in

blairconrad avatar Sep 01 '23 10:09 blairconrad

Using Moq: A Simple Guide to Mocking for .NET accurate?

I think your fear is that you'd configure a strict Fake, use it in your system under test, and a bonus method would be called and the system under test would eat the exception raised by the Fake and nobody would know that something unexpected happened?

Without changing FakeItEasy's code, today you could get the calls that were received and examine them, seeing if any of them were outside the ones you allow-listed. Then again with a complex strict Fake, I can see how this would get onerous. And brittle.

This seems like a useful feature. What think you, @thomaslevesque?

I have an idea how to implement this, but the stuff for that is not accessible from consumer code.

Oh, I'd be keen to hear what you thought.

One implementation that I thought of, that might not be too disruptive, would be to add a member to FakeItEasy.Core.StrictFakeRule, capturing the unanticipated calls that are received. Then one could check the Fake to see if the list were empty.

Oh! This is implementable in user code. At least for a proof of concept. Make a copy of StrictFakeRule. Add the list of received calls that I just mentioned. Then manually apply that rule to your Fake. And you'll have the rule sitting right there and you can interrogate it.

blairconrad avatar Sep 01 '23 10:09 blairconrad

My first thought when I started reading the issue was "just use a strict fake", but it's true that the ExpectationException could be caught in the SUT and never seen from the tests...

for use cases where strict fakes would need complex setups.

Do you mean that you can't use a strict fake because there would be too many calls to configure, so you want to rely on the default fake behavior? But in this case, all those unconfigured calls would be caught by VerifyNoOtherCalls, wouldn't they? So basically you have to configure them, if you want to make sure no unexpected call happens.

thomaslevesque avatar Sep 01 '23 12:09 thomaslevesque

Hi guys!

Yes, that method's description is accurate. In other words, the mock not only tracks the calls on it, but also for which methods Verify has been called. These lists are then compared.

To better explain my use case: Sometimes, an interface might be quite large (which I am of course not a big fan of), and setting up its methods for strict faking would be quite cumbersome. Moreover, when I would then verify that certain calls have been made (especially using ordered assertions), I would again have to assert on the same methods again.

ChristoWolf avatar Sep 01 '23 15:09 ChristoWolf

I think I'm more confused now. I had thought it would verify that no calls were made other than the ones configured, not asserted.

Is this supposed to be used when the Fake isn't strict? As a way to avoid an overly complicated strict Fake configuration?

Maybe show us a sample usage?

blairconrad avatar Sep 01 '23 16:09 blairconrad

Sorry about being unclear.

I had thought it would verify that no calls were made other than the ones configured, not asserted.

That's the thing though, it should verify that no other calls were made except for the expected (i.e. the already asserted) calls. That would simplify the setup quite a lot, because this does not need strict configuration and we could often simply use the fresh, loose fake directly for verification.

I unfortunately can't access a machine at the moment, but will try to whip up something on Monday!

ChristoWolf avatar Sep 01 '23 16:09 ChristoWolf

Sorry about being unclear.

Oh, don't be sorry. Maybe it's me. It often is.

blairconrad avatar Sep 01 '23 16:09 blairconrad

There's been no activity in this issue for some time, so we're closing it. We can reopen the issue in the future should sufficient interest arise.

blairconrad avatar Apr 18 '24 14:04 blairconrad

Just wanted to mention that I actually followed your advice and simply made the fake strict. I now think that that's actually the cleanest solution, it just doesn't convey the intent as well, but I usually just add according comments in my code to signify the intent.

ChristoWolf avatar Jun 18 '24 13:06 ChristoWolf

Thanks for the update, @ChristoWolf. I hope your workaround/solution continues to work for you.

blairconrad avatar Jun 18 '24 13:06 blairconrad