使用 Moq 模拟扩展 IList 的接口
Using Moq to mock an interface that extends IList
我正在尝试模拟一个扩展 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]);
}
这里的问题出在 AddRange 函数的内部:https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,79de3e39e69a4811
您可以看到,第一次尝试是将其转换为 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));
我正在尝试模拟一个扩展 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]);
}
这里的问题出在 AddRange 函数的内部:https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,79de3e39e69a4811
您可以看到,第一次尝试是将其转换为 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));