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

如何使用Moq返回未完成Task<List>以测试含Task.WhenAll的代码

问题原因

你之前的写法存在问题:直接通过new Task<List<SourceOneDto>>()创建的是未启动的冷任务,该任务永远不会进入完成状态,因此Task.WhenAll()会一直陷入等待,无法得到预期结果。

正确实现方式

根据你的场景可以选择以下三种实现方案:

方案1:返回已完成的Task(无需模拟异步延迟)

使用Task.FromResult()包裹返回结果,直接生成已完成状态的Task:

// 配置ReturnA的模拟返回
var mockReturnAResult = new List<SourceOneDto>
{
    new SourceOneDto { Data = "模拟返回数据" }
};
_sourceServiceMock.Setup(s => s.ReturnA())
    .Returns(Task.FromResult(mockReturnAResult));

// 配置ReturnB的模拟返回
_sourceServiceMock.Setup(s => s.ReturnB())
    .Returns(Task.FromResult(new List<SourceTwoDto>()));

方案2:使用Moq内置语法简化配置(Moq 4.16及以上版本支持)

直接调用ReturnsAsync()方法,Moq会自动帮你封装Task:

// 配置ReturnA的模拟返回
_sourceServiceMock.Setup(s => s.ReturnA())
    .ReturnsAsync(new List<SourceOneDto>
    {
        new SourceOneDto { Data = "模拟返回数据" }
    });

// 配置ReturnB的模拟返回
_sourceServiceMock.Setup(s => s.ReturnB())
    .ReturnsAsync(new List<SourceTwoDto>());

方案3:模拟带延迟的未完成Task(还原真实异步场景)

如果需要模拟和真实业务一致的、需要等待一段时间才完成的Task,可直接传入异步委托:

// 模拟ReturnA延迟1ms后返回结果,和你示例中的真实实现逻辑一致
_sourceServiceMock.Setup(s => s.ReturnA())
    .Returns(async () =>
    {
        await Task.Delay(1);
        return new List<SourceOneDto>
        {
            new SourceOneDto { Data = "模拟返回数据" }
        };
    });

// 模拟ReturnB延迟2ms后返回结果
_sourceServiceMock.Setup(s => s.ReturnB())
    .Returns(async () =>
    {
        await Task.Delay(2);
        return new List<SourceTwoDto>();
    });

注意事项

你示例代码中使用a.Result[0].Data获取结果的写法存在死锁风险,建议改为(await a)[0].Data的异步写法读取返回值。

内容的提问来源于stack exchange,提问作者Paul_87

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 18:36:00