使用Moq模拟扩展IList的接口

时间:2019-08-23 19:51:41

标签: c# moq

我正在尝试模拟扩展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]);
}

1 个答案:

答案 0 :(得分:1)

这里的问题出在AddRange函数的内部:https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,79de3e39e69a4811

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

因此,最简单的方法是将其替换为类似的内容。无论如何,您都可以进行模拟枚举。也可以使用LINQ缩短它。

foreach(var item in mockTest.Object)
{
    testList.Add(item);
}

如果要使用MOQ进行此操作,则应该适合以下情况:

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