Description
Describe the solution you'd like
If a mock throws an exception, we should track that on the expectations and use that knowledge to not throw an exception in Verify()
. The reason why is because of RockContext
. Let's say we did something like this:
public interface IThing
{
void DoStuff();
void DoOtherStuff();
}
using var context = new RockContext();
var expectations = context.Create<IThing>();
expectations.Methods.DoOtherStuff();
var mock = expectations.Instance();
mock.DoStuff();
We have an expectation set for DoOtherStuff()
, but we call DoStuff()
. That throws an ExpectationException
, but what happens is in the finally
block, Verify()
is called and that will throw a VerificationException
stating that DoOtherStuff()
was never invoked. Which is true, but this is masking the exception thrown from the mock's DoStuff()
implementation. We don't want to do that, as it may be confusing to the user.
I think the way to handle this is to generate a private bool WasExceptionThrown { get; set; }
on the generated expectations type, and when the mock implementation is going to throw an exception, it sets this flag. Then, in Verify()
, we only do verification if WasInstanceInvoked
is true
and WasExceptionThrown
is false
.
If a user defines a callback that throws an exception, we can't do anything about that. We're assuming the user is doing that on purpose and will check for that exception in their code as an expected behavior.
Sadly, this adds more code to a mock member's implementation, so performance numbers will go up a bit (sad!). But it'll be a very small perf hit, and it's necessary for correctness.
Describe alternatives you've considered
Keep things the way they are, but that's kind of bad.