如何使用moq </t>模拟ReadOnlyCollection <t>属性

时间:2012-04-17 21:36:27

标签: c# moq

我正在尝试模拟这个ReadOnlyCollection属性:

private readonly IList<MyClass> myList = new List<MyClass>();
public virtual ReadOnlyCollection<MyClass> MyList
{
   get
   {
       return new ReadOnlyCollectionBuilder<MyClass>(this.myList).ToReadOnlyCollection();
   }
}

使用此模拟(如here所示):

IList<MyClass> mockList = GetElements();
mockObj.SetupGet<IEnumerable<MyClass>>(o => o.myList).Returns(mockList);

但是在运行时我得到一个InvalidCastException:

Unable to cast object of type 'System.Collections.Generic.List`1[MyClass]' to
type 'System.Collections.ObjectModel.ReadOnlyCollection`1[MyClass]'.

我做错了什么?

3 个答案:

答案 0 :(得分:1)

您无法模拟私有只读属性myList,您可以执行的操作是覆盖公共属性MyList,因为它标记为虚拟。为此,您需要更新此代码:

IList<MyClass> mockList = GetElements();
mockObj.SetupGet<IEnumerable<MyClass>>(o => o.myList).Returns(mockList);

到此:

var mockList = new ReadOnlyCollection<MyClass>(GetElements());
mockObj.Setup(o => o.MyList).Returns(mockList);

答案 1 :(得分:1)

假设您的代码看起来很像(否则它将无法编译):

// Arrange
IList<MyClass> stakeHoldersList= GetElements();
mockObj.SetupGet<IEnumerable<MyClass>>(o => o.MyList).Returns(stakeHoldersList);
// Act on SUT which uses mockObj

您拥有类型为ReadOnlyCollection<MyClass>的属性MyList,但您尝试返回IEnumerable<MyClass>。这就是为什么你得到那个错误。所以,改变:

ReadOnlyCollection<MyClass> stakeHoldersList = new ReadOnlyCollection<MyClass>(GetElements());
mockObj.SetupGet<ReadOnlyCollection<MyClass>>(o => o.MyList).Returns(stakeHoldersList);

要避免此类运行时错误,请不要指定SetupGet方法的类型。在这种情况下,将从属性类型推断返回值类型,您将立即收到错误(如果返回值类型与属性类型不匹配,代码将无法编译):

mockObj.SetupGet(o => o.MyList).Returns(stakeHoldersList);

答案 2 :(得分:0)

有点晚了,但是我认为这可以减少一些代码。

mockObj.SetupGet(o => o.MyList).Returns(GetElements().AsReadOnly);
相关问题