You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:10:49