我正在尝试在Microsoft.Office.Interop.Word程序集中模拟Variables接口
var variables = new Mock<Variables>();
variables.Setup(x => x.Count).Returns(2);
variables.Setup(x => x.GetEnumerator()).Returns(TagCollection);
private IEnumerator TagCollection()
{
var tag1 = new Mock<Variable>();
tag1.Setup(x => x.Name).Returns("Foo");
tag1.Setup(x => x.Value).Returns("Bar");
var tag2 = new Mock<Variable>();
tag2.Setup(x => x.Name).Returns("Baz");
tag2.Setup(x => x.Value).Returns("Qux");
yield return tag1.Object;
yield return tag2.Object;
}
我的代码如下所示:
// _variables is an instance of Variables interface
var tags = from variable in _variables.OfType<Variable>()
where variable.Name == "Foo"
select variable.Value;
var result = tags.ToList();
上面代码中的最后一行抛出NullReferenceException。如果我使用foreach循环迭代_variables集合,我可以毫无问题地访问Variable的模拟对象。我在这里做错了什么?
答案 0 :(得分:7)
尝试:
variables
.As<IEnumerable>()
.Setup(x => x.GetEnumerator()).Returns(TagCollection);
有两种不同的方法,一种在基本接口中声明,另一种在Variables
中声明。
直接foreach
时,会调用后者,因为该方法 隐藏 基本类型中相同的成员。当foreach
方法存在时,public
会调用IEnumerable
方法,在这种情况下,.OfType<Variable>()
无关紧要。
当您调用IEnumerable
Linq扩展名时,引用将转换为_variables.GetEnumerator();
接口,并且名称隐藏不再存在。基本接口上的方法称为。
这就像是:
之间的区别((IEnumerable)_variables).GetEnumerator();
和
public class TheTypeMoqMakes : Variables
{
Enumerator Variables.GetEnumerator()
{
// Use return value from after
// expression tree you provided with 'Setup' without 'As'.
// If you did not provide one, just return null.
}
Enumerator IEnumerable.GetEnumerator()
{
// Use return value from after
// expression tree you provided with 'Setup' with 'As<IEnumerable>'.
// If you did not provide one, just return null.
}
// other methods and properties
}
您可以将模拟Moq视为:
Setup
如果成员不是MockBehavior.Loose
,Moq返回null的原因是你有MockBehavior.Strict
。请始终考虑Variables
。
在这种情况下,我无法理解为什么{{1}}接口chose to use method hiding的作者。