As we unit test obsessed folks know, asserting that a method was not called is often equally important to the correctness of a test suite as asserting that a method was called.
With Isolator, fakes created with Isolate.Fake.Instance<T>(Members.MustSpecifyReturnValues) have the behavior of throwing if a non-void method call is made on that fake without first having set the method's return value with Isolate.WhenCalled(() => fake.NonVoidMethod()).WillReturn(returnValue).
This behavior is perfect if only non-void method calls can break your code under test.
For ensuring that no breaking extraneous void method calls are made, the user appears to be out of luck: no exception is thrown when a void method is called on a Members.MustSpecifyReturnValues fake (as the name "MustSpecifyReturnValues" well indicates).
Given this behavior, for those void methods with side effects that must not be experienced in order for my code under test to be correct, I have taken to converting such void methods to methods returning a dummy value.
Here is some example code of what that looks like:
public class Class
{
public int NonVoidMethod()
{
return 0;
}
public void VoidMethod()
{
}
public DummyReturnValue VoidMethodByAnyOtherName()
{
return DummyReturnValue.Value;
}
}
public struct DummyReturnValue
{
public static readonly DummyReturnValue Value = new DummyReturnValue();
}
[TestFixture]
public class Tests
{
[Test]
public void Test()
{
var c = Isolate.Fake.Instance<Class>(Members.MustSpecifyReturnValues);
c.NonVoidMethod(); // Throws
c.VoidMethod(); // Does not throw. c.VoidMethod() can be introduced into the code under test with no corresponding break in the unit tests (absent a call to WasNotCalled()).
c.VoidMethodByAnyOtherName(); // Throws
}
}
Hackish for sure and bound to raise questions from colleagues such as "why the hell are you returning this dummy value here?". "Oh, because Isolator only strictly mocks non-void methods." It would be great if Members.MustSpecifyAll existed in a future version of Isolator.