Moq验证没有它 - 什么样的比较?

时间:2014-06-25 09:05:39

标签: c# moq verify

当使用带有Verify的Moq时,为了声明已使用指定参数调用某个方法,可以使用不同类型的语法;一个是"它"语法,像这样

mock.Verify(c => c.SomeMethod(It.Is<string>(s => s == ExpectedString)));

这里发生的是检查SomeMethod被调用的参数是否与ExpectedString相等。另一种可能的语法是没有&#34; It&#34;:

mock.Verify(c => c.SomeMethod(ExpectedString));

应该给出相同的结果。根据我在不同论坛上能够找到的,不同之处在于后者是一个识别检查(引用等于)(值类型除外)。

但是,我的问题是参数属于Collection类型。在.NET中,Equals上的Collection<T>只是继承自object,因此以下验证:

mock.Verify(c => c.SomeMethod(new Collection<string> { ExpectedString }));
鉴于集合在验证中被实例化,因此不应该传递

,因此不可能是在生产代码中实例化的同一实例。然而,它有效,这表明Moq做了一个CollectionAssert或类似的东西,与我能找到的信息相反。

这是一个代码示例,说明了行为,测试通过,但我认为如果Moq使用引用等于比较它应该失败。

[TestMethod]
public void Test()
{
    var mock = new Mock<IPrint>();
    const int ExpectedParam = 1;
    var test = new TestPrinter { Printer = mock.Object, Expected = ExpectedParam };

    test.Do();

    mock.Verify(c => c.Print(new Collection<int> { ExpectedParam }));
}

public interface IPrint
{
    void Print(Collection<int> numbers);
}

public class TestPrinter
{
    public IPrint Printer { get; set; }

    public int Expected { get; set; }

    public void Do()
    {
        Printer.Print(new Collection<int> { Expected });
    }
}

有谁知道这是否是Moq(版本4.1)的预期行为?某个版本级别的行为是否发生了变化?

1 个答案:

答案 0 :(得分:5)

这是desired behaviour并且是added to moq in January 2009(版本3.0.203.1)。

如果moq找到IEnumerable,它会使用SequenceEqual来比较实际参数和设置中使用的参数,否则它只使用Equals

Here's相关的代码:

internal class ConstantMatcher : IMatcher
{
    ...

    public bool Matches(object value)
    {
        if (object.Equals(constantValue, value))
        {
            return true;
        }

        if (this.constantValue is IEnumerable && value is IEnumerable)
        {
            return this.MatchesEnumerable(value);
        }

        return false;
    }

    private bool MatchesEnumerable(object value)
    {
        var constValues = (IEnumerable)constantValue;
        var values = (IEnumerable)value;
        return constValues.Cast<object>().SequenceEqual(values.Cast<object>());
    }
}