当使用带有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)的预期行为?某个版本级别的行为是否发生了变化?
答案 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>());
}
}