C# 使用Moq模拟扩展IList的接口

C# 使用Moq模拟扩展IList的接口,c#,moq,C#,Moq,我试图模拟一个扩展IList的接口,并使模拟作为IEnumerable工作。我希望模拟对象包含一个可枚举的用户列表,而不是枚举结果。如果我将接口ITestEnumerable扩展更改为IEnumerable而不是IList,则下面的代码可以工作 public interface ITestEnumerable : IList<User> { } [Fact] public void TestTest() { //Arrange var fakes = new Li

我试图模拟一个扩展IList的接口,并使模拟作为IEnumerable工作。我希望模拟对象包含一个可枚举的用户列表,而不是枚举结果。如果我将接口ITestEnumerable扩展更改为IEnumerable而不是IList,则下面的代码可以工作

public interface ITestEnumerable : IList<User>
{

}

[Fact]
public void TestTest()
{
    //Arrange
    var fakes = new List<User>()
    {
        new User() { DisplayName = "Joe Smith", Mail = "jsmith@test.com" },
        new User() { DisplayName = "Jane Doe", Mail = "jdoe@test.com" }
    };
    var mockTest = new Mock<ITestEnumerable>();
    mockTest.Setup(t => t.Count).Returns(() => fakes.Count());
    mockTest.Setup(t => t[It.IsAny<int>()]).Returns<int>(i => fakes.ElementAt(i));
    mockTest.As<IEnumerable<User>>().Setup(t => t.GetEnumerator()).Returns(() => fakes.GetEnumerator());
    var testList = new List<User>();

    //Act
    testList.AddRange(mockTest.Object);

    //Assert
    Assert.NotNull(testList[0]);
}
公共接口ITestEnumerable:IList
{
}
[事实]
公共void TestTest()
{
//安排
var fakes=新列表()
{
新用户(){DisplayName=“Joe Smith”,邮件=”jsmith@test.com" },
新用户(){DisplayName=“Jane Doe”,邮件=”jdoe@test.com" }
};
var mockTest=new Mock();
mockTest.Setup(t=>t.Count).返回(()=>fakes.Count());
Setup(t=>t[It.IsAny()).Returns(i=>fakes.ElementAt(i));
mockTest.As().Setup(t=>t.GetEnumerator())。返回(()=>fakes.GetEnumerator());
var testList=新列表();
//表演
AddRange(mockTest.Object);
//断言
Assert.NotNull(testList[0]);
}

这里的问题在于AddRange函数的内部:

您可以看到,第一次尝试是将其强制转换为ICollection,然后有一个完整的CopyTo流

所以最简单的方法就是用这样的东西来代替它。不管怎样,您都可以使用模拟枚举器。它也可以用LINQ缩短

foreach(var item in mockTest.Object)
{
    testList.Add(item);
}
如果你想用最小起订量来做这件事,像这样的东西应该适合:

mockTest.As<ICollection<User>>().Setup(t => t.CopyTo(It.IsAny<User[]>(), It.IsAny<int>())).Callback<User[], int>((u,c) => fakes.CopyTo(u,c));
mockTest.As().Setup(t=>t.CopyTo(It.IsAny(),It.IsAny()).Callback((u,c)=>fakes.CopyTo(u,c));

AddRange
将尝试将
IEnumerable
强制转换为
ICollection
,并使用
CopyTo
而不是迭代
IEnumerable
您的界面到底向
IList
添加了哪些内容。您是否考虑过使用组合而不是继承?通常最好不要扩展现有的集合,您的界面看起来像是由继承自
List
的东西实现的。我试图模拟IGraphServiceUsersCollectionPage,它是Microsoft图形服务库的一部分。它实现了IList。测试中的方法使用此库与Office 365对话,我不希望在测试期间发生这种情况。上面的代码只是为了说明问题而进行的简化。您可能不想模仿,而只想使用一个实现,或者是一个真实的实现,或者只是一个假的实现来进行测试。