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

如何将Task.Delay替换为Func<>以提升C#异步代码可测试性

解决方案

推荐使用Func<int, Task>类型的委托注入,不要使用Func<int, int>方案,理由如下:

  • 如果你使用Func<int, int>:仅能抽离延迟参数的获取逻辑,核心的Task.Delay调用仍然硬编码在业务代码中,单元测试运行时会产生真实的等待耗时,严重影响测试执行效率,仅能实现参数校验的需求,收益很低。
  • 如果你使用Func<int, Task>:可以把整个延迟执行逻辑完全抽离,生产环境默认实现为ms => Task.Delay(ms)不影响原有逻辑;测试环境可以直接返回Task.CompletedTask跳过真实等待,同时还能在模拟实现中捕获传入的延迟参数,完全满足你参数校验的需求,可测试性更高。

业务代码改造示例

public class YourQueueService
{
    private readonly IQueueClient _client;
    private readonly int _retryDelayMs;
    // 注入延迟执行委托
    private readonly Func<int, Task> _delayExecutor;

    // 构造函数提供默认实现,不影响原有业务调用
    public YourQueueService(IQueueClient client, int retryDelayMs, Func<int, Task> delayExecutor = null)
    {
        _client = client;
        _retryDelayMs = retryDelayMs;
        // 生产环境默认使用原生Task.Delay
        _delayExecutor = delayExecutor ?? (delayMs => Task.Delay(delayMs));
    }

    private async Task Enqueue(object request)
    {
        try
        {
            await _client.Enqueue(request);
        }
        catch (Exception e)
        {
            // 替换原有硬编码的Task.Delay
            await _delayExecutor(_retryDelayMs);
            await Enqueue(request);
        }
    }
}

单元测试示例(无第三方依赖的简单实现)

[Test]
public async Task Enqueue_OnException_UsesCorrectDelay()
{
    // 1. 准备测试环境
    var mockClient = new MockQueueClient(alwaysThrow: true);
    int capturedDelay = 0;
    // 模拟延迟委托,捕获参数且不产生真实等待
    Func<int, Task> mockDelay = delayMs =>
    {
        capturedDelay = delayMs;
        return Task.CompletedTask;
    };
    var service = new YourQueueService(mockClient, retryDelayMs: 1000, mockDelay);

    // 2. 执行测试逻辑
    try
    {
        await service.Enqueue(new object());
    }
    catch
    {
        // 忽略模拟客户端抛出的异常
    }

    // 3. 校验延迟参数是否符合预期
    Assert.AreEqual(1000, capturedDelay);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:15:03