结果视图未在 VS 调试器中正确枚举
Result view not enumerating correctly in VS Debugger
如果我模拟一个集合让 Moq 实现 GetEnumerator 回调 GetEnumerator一个不同的集合,如果我调用 MoveNext/Current 和 foreach.
我会得到正确的结果
当我尝试使用 Visual Studio 调试器的 结果视图 时,我得到 "Enumeration yielded no results"。是否有一个原因?不就是枚举缓存吗?
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;
这肯定与调试器与对象交互的方式有关。我在控制台应用程序中重新创建了您的示例,但添加了一个回调,因此每次调用 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()
被调用了两次。第一个将 return ArrayList 的实际枚举器,而后续调用将 return null。似乎调试器正在枚举第二个调用,因此 "Enumeration yielded no results" 消息。
因此,在上面的情况下,调试器已经调用了 GetEnumerator
的一个模拟调用,如果我继续 运行 应用程序,则 foreach 会在不执行任何操作的情况下完成。同样,因为调试器已经调用了一个,模拟的 GetEnumerator
.
不真实 "answer" 但可能有助于阐明您所看到的内容。
感谢@Patrick Steele 帮助我意识到我的错误:
问题在这里:
[...].Returns(dbParameters.GetEnumerator());
正在获取枚举器实例并将其用于模拟。第一次使用后,它可能会被丢弃并以某种方式设置为 null。
如建议的那样,结果视图正在枚举两次并显示第二次为空的结果(和一个问号,因为显然处置的枚举器有问题)。
为了在随后的枚举中存活下来,它需要每次使用 lambda 来查询一个新的模拟:
[...].Returns(() => dbParameters.GetEnumerator());
如果我模拟一个集合让 Moq 实现 GetEnumerator 回调 GetEnumerator一个不同的集合,如果我调用 MoveNext/Current 和 foreach.
我会得到正确的结果当我尝试使用 Visual Studio 调试器的 结果视图 时,我得到 "Enumeration yielded no results"。是否有一个原因?不就是枚举缓存吗?
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;
这肯定与调试器与对象交互的方式有关。我在控制台应用程序中重新创建了您的示例,但添加了一个回调,因此每次调用 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()
被调用了两次。第一个将 return ArrayList 的实际枚举器,而后续调用将 return null。似乎调试器正在枚举第二个调用,因此 "Enumeration yielded no results" 消息。
因此,在上面的情况下,调试器已经调用了 GetEnumerator
的一个模拟调用,如果我继续 运行 应用程序,则 foreach 会在不执行任何操作的情况下完成。同样,因为调试器已经调用了一个,模拟的 GetEnumerator
.
不真实 "answer" 但可能有助于阐明您所看到的内容。
感谢@Patrick Steele 帮助我意识到我的错误:
问题在这里:
[...].Returns(dbParameters.GetEnumerator());
正在获取枚举器实例并将其用于模拟。第一次使用后,它可能会被丢弃并以某种方式设置为 null。
如建议的那样,结果视图正在枚举两次并显示第二次为空的结果(和一个问号,因为显然处置的枚举器有问题)。
为了在随后的枚举中存活下来,它需要每次使用 lambda 来查询一个新的模拟:
[...].Returns(() => dbParameters.GetEnumerator());