使用Moq验证使用ref参数的调用

ili*_*rit 3 moq ref verify

如何验证使用Moq调用"CallWithRef"方法?

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));
}
Run Code Online (Sandbox Code Playgroud)

Pat*_*irk 7

这在Moq 4.8.0中已经变得更好了,详情请参见其他答案It.Ref!


Verify在Moq中调用对ref参数执行严格的相等检查.当参数是引用类型时(如示例所示),只有当实际值和期望值是相同的引用时,Moq使用参数匹配器才会成功.这是因为它用于验证相等性.object.ReferenceEquals(expected, actual)

Moq快速入门中提到了这种行为(尽管可能会更加彻底):

// 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);
Run Code Online (Sandbox Code Playgroud)

在您的示例中,It.IsAny<List<string>>()实际上最后返回default(T),因此您要与创建null的新实例进行比较,根据匹配器的实现将失败.List<string>DoStuff

这显然是一个玩具示例,因此我无法建议您应该做什么,但如果您修改DoStuff为接受列表而不是创建自己的列表,您可以像这样测试它:

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));
Run Code Online (Sandbox Code Playgroud)


Spe*_*ton 7

从版本 4.8.0 开始,现在可以使用 Moq 来实现这一点。这是链接: https: //github.com/moq/moq4/issues/479

你可以像这样传递 errorList

ref It.Ref<List<string>>.IsAny
Run Code Online (Sandbox Code Playgroud)