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

时间:2014-09-11 11:11:02

标签: moq ref verify

如何验证" CallWithRef"使用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));
}

2 个答案:

答案 0 :(得分:7)

Moq 4.8.0中的情况有所改善,请参阅此处的其他答案,详细了解It.Ref


对Moq中的Verify的调用会对ref个参数执行严格的相等检查。当参数是引用类型时(如示例所示),仅当实际值和期望值是相同引用时,argument matcher that Moq uses才会成功。这是因为它使用object.ReferenceEquals(expected, actual)来验证相等性。

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);

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

这显然是一个玩具示例,因此我无法建议您应该做什么,但如果您修改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));

答案 1 :(得分:3)

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

您可以像这样传递errorList

ref It.Ref<List<string>>.IsAny