How can I verify that the "CallWithRef" method was called using Moq?
public interface ITest
{
void CallWithoutRef(string value, List<string> errors);
void CallWithRef(string value, ref List<string> errors);
}
public class Foo
{
private ITest testInterface;
public Foo(ITest testInterface)
{
this.testInterface = testInterface;
}
public void DoStuff(string value)
{
var errorList = new List<string>();
testInterface.CallWithoutRef(value, errorList);
testInterface.CallWithRef(value, ref errorList);
}
}
[TestMethod]
public void VerifyTestInterfaceCalls()
{
var expectedValue = Path.GetRandomFileName();
var mockTestInterface = new Mock<ITest>();
var foo = new Foo(mockTestInterface.Object);
foo.DoStuff(expectedValue);
mockTestInterface.Verify(x => x.CallWithoutRef(expectedValue, It.IsAny<List<string>>()));
// Test fails here:
var errorList = It.IsAny<List<string>>();
mockTestInterface.Verify(x => x.CallWithRef(expectedValue, ref errorList));
}
This has changed for the better in Moq 4.8.0, see the other answer here for details on It.Ref
!
Calls to Verify
in Moq perform a strict equality check for ref
arguments. When the argument is a reference type (like in your example), the argument matcher that Moq uses succeeds only if the actual and expected values are the same reference. This is because it uses object.ReferenceEquals(expected, actual)
to verify equality.
This behavior is mentioned (although it could be a little more thorough) in the Moq Quickstart:
// ref arguments
var instance = new Bar();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(foo => foo.Submit(ref instance)).Returns(true);
In your example, It.IsAny<List<string>>()
actually returns default(T)
in the end, so you're comparing null
to the new instance of a List<string>
created in DoStuff
, which according to the matcher's implementation will fail.
This is obviously a toy example so I can't suggest what you should do, but if you modify DoStuff
to accept the list rather than create its own, you could test it like this:
var errorList = It.IsAny<List<string>>();
// var errorList = new List<string>(); // also works
foo.DoStuff(expectedValue, errorList);
mockTestInterface.Verify(x => x.CallWithoutRef(expectedValue, It.IsAny<List<string>>()));
mockTestInterface.Verify(x => x.CallWithRef(expectedValue, ref errorList));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With