Moq SetupSequence结合Queue仅首次执行生效问题求助
问题原因分析
你代码里的核心问题是:mock.SetupSequence(x => x.GetNumber()).Returns(numberQueue.Dequeue) 中,numberQueue.Dequeue 是直接执行了方法,把第一次出队的结果4传给了Returns,而非将Dequeue作为委托交给Moq,让它在每次调用GetNumber时执行。因此SetupSequence实际只设置了一次返回值4,后续调用因无对应设置,返回int的默认值0。
解决方案
方案1:循环构建SetupSequence
遍历队列元素,逐个为SetupSequence添加带委托的返回逻辑,确保每次调用都执行出队操作:
var numberQueue = new Queue<int>(new[] { 4, 8, 16, 43}); var mock = new Mock<ITest>(); var setup = mock.SetupSequence(x => x.GetNumber()); while (numberQueue.Count > 0) { // 传入委托,让Moq每次调用时执行Dequeue setup.Returns(() => numberQueue.Dequeue()); } int x1 = mock.Object.GetNumber(); // 4 int x2 = mock.Object.GetNumber(); // 8 int x3 = mock.Object.GetNumber(); // 16 int x4 = mock.Object.GetNumber(); // 43 x1.Should().Be(4); // 通过 x2.Should().Be(8); // 通过 x3.Should().Be(16); // 通过 x4.Should().Be(43); // 通过
方案2:直接Setup动态委托(更简洁)
若无需严格限制调用次数,可跳过SetupSequence,直接在Setup中返回动态委托:
var numberQueue = new Queue<int>(new[] { 4, 8, 16, 43}); var mock = new Mock<ITest>(); mock.Setup(x => x.GetNumber()) .Returns(() => numberQueue.Dequeue()); // 每次调用都执行出队 // 后续调用与断言均可正常工作
适配IDataReader的Mock场景
针对IDataReader的动态Mock,核心思路一致:将模拟数据存入队列,在Setup对应方法(如Read、GetInt32)时返回从队列取数的委托。示例如下:
// 模拟两行int类型的字段数据 var dataQueue = new Queue<int>(new[] { 100, 200 }); var readerMock = new Mock<IDataReader>(); // 模拟Read方法:队列有数据时返回true,为空返回false readerMock.SetupSequence(r => r.Read()) .Returns(() => dataQueue.Count > 0) .Returns(() => dataQueue.Count > 0) .Returns(false); // 模拟读取指定索引的Int32字段,每次从队列取数据 readerMock.Setup(r => r.GetInt32(It.IsAny<int>())) .Returns(() => dataQueue.Dequeue()); // 使用Mock的IDataReader while (readerMock.Object.Read()) { var value = readerMock.Object.GetInt32(0); // 第一次取到100,第二次取到200 }
内容的提问来源于stack exchange,提问作者miquel09
相关产品推荐
相关产品推荐

