如果我模拟了一个集合,让 Moq 实现 GetEnumerator 回调其他集合的 GetEnumerator ,我会得到正确的结果调用MoveNext / Current和foreach。
当我尝试使用Visual Studio调试器中的结果视图时,我得到“枚举没有产生结果”。是否有一个原因?是不是只是枚举和缓存它?
var dbParameterMock1 = CreateDbParameterMock("@Parameter1", 1);
var dbParameters = new ArrayList { dbParameterMock1.Object };
var dbParameterCollectionMock = new Mock<DbParameterCollection>();
dbParameterCollectionMock.Setup(collection => collection.GetEnumerator()).Returns(dbParameters.GetEnumerator());
return dbParameterCollectionMock;
答案 0 :(得分:1)
它肯定与调试器与对象交互的方式有关。我在控制台应用程序中重新创建了您的示例,但添加了一个回调,因此每次调用GetEnumerator
时都会知道:
var dbParameterMock1 = new Mock<DbParameter>().SetupAllProperties();
dbParameterMock1.Object.ParameterName = "@Parameter1";
dbParameterMock1.Object.Value = 1;
var dbParameters = new ArrayList { dbParameterMock1.Object };
var dbParameterCollectionMock = new Mock<DbParameterCollection>();
dbParameterCollectionMock.Setup(collection => collection.GetEnumerator())
.Returns(dbParameters.GetEnumerator())
.Callback(() => Console.WriteLine("GetEnumeratorCalled"));
foreach (DbParameter p in dbParameterCollectionMock.Object)
{
Console.WriteLine(p.ParameterName);
}
如果我在foreach上设置了断点,请运行代码,然后使用调试器查看dbParameterCollectionMock.Object
,我会看到GetEnumerator()
被调用两次。第一个将返回ArrayList的实际枚举器,而后续调用将返回null。似乎调试器正在枚举第二个调用,因此&#34;枚举没有产生任何结果&#34;消息。
因此,在上面的情况下,调试器已经调用了GetEnumerator
的一个模拟调用,如果我继续运行应用程序,则foreach完成而不做任何事情。同样,因为调试器已经调用了一个模拟的GetEnumerator
。
不是真的&#34;答案&#34;但可能有助于阐明你所看到的内容。
答案 1 :(得分:0)
感谢@Patrick Steele帮助我实现了我的错误:
问题在于:
[...].Returns(dbParameters.GetEnumerator());
获取枚举器实例并将其用于模拟。一旦它第一次被使用它可能被处置并以某种方式设置为空。
正如所建议的那样,结果视图枚举两次并显示第二次的结果为空(并且问号显然是处置的枚举器有问题)。
为了在后续枚举中生存,每次使用lambda进行模拟时,它需要查询一个新的:
[...].Returns(() => dbParameters.GetEnumerator());