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

如何单元测试finally块中Response.OnCompleted()内的代码?

问题:如何手动触发Response.OnCompleted委托进行单元测试

被测代码

public async Task<IActionResult> Get([FromBody] object request)
{
    try
    {
        return Ok("Okay Message");
    }
    catch (Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError, FormProblemDetails(ex, StatusCodes.Status500InternalServerError));
    }
    finally
    {
        Response.OnCompleted(async () =>
        {
            if (Response.StatusCode == StatusCodes.Status200OK)
            {
                // unit test this method.
                await DoSomeWork();
            }
        });
    }
}

private async Task DoSomeWork()
{
  // unit test the code present here.
}

相关单元测试代码

//Arrange;

var httpContext = new DefaultHttpContext();
httpContext.Request.Headers["Authorization"] = "somedummytoken";
httpContext.Response.OnCompleted(null);


MyController controller = new MyController()
{
    ControllerContext = new ControllerContext() { HttpContext = httpContext }
};

用户问题

我想要对Response.OnCompleted委托内的代码进行单元测试,但目前该回调在单元测试中不会被触发,请问如何手动触发Response.OnCompleted委托?


解决方案

单元测试场景下DefaultHttpResponse的OnCompleted回调不会自动执行,可通过反射获取内部维护的回调列表并手动触发:

  1. 清理无效代码:先删掉测试代码里的httpContext.Response.OnCompleted(null),这行添加的空回调会干扰后续测试。

  2. 调用控制器方法后执行回调:

// Arrange
var httpContext = new DefaultHttpContext();
httpContext.Request.Headers["Authorization"] = "somedummytoken";
var controller = new MyController()
{
    ControllerContext = new ControllerContext() { HttpContext = httpContext }
};
var request = new object(); // 替换为实际的请求对象

// Act
var result = await controller.Get(request);

// 手动触发OnCompleted回调
var response = httpContext.Response as DefaultHttpResponse;
var callbacksField = typeof(DefaultHttpResponse).GetField(
    "_onCompletedCallbacks", 
    BindingFlags.NonPublic | BindingFlags.Instance
);
var callbacks = callbacksField.GetValue(response) as List<Func<Task>>;

if (callbacks != null)
{
    foreach (var callback in callbacks)
    {
        await callback();
    }
}

// Assert
// 验证DoSomeWork的执行情况,比如通过依赖注入的Mock对象验证方法调用

优化建议

如果DoSomeWork依赖外部服务,建议将该服务抽象为接口并注入控制器,用Moq等框架创建Mock对象,执行回调后直接验证Mock方法的调用情况,避免依赖反射,让测试更健壮。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:20:20