ASP.NET Core集成测试中如何配置IHttpActivityFeature?
解决ASP.NET Core测试服务器中
IHttpActivityFeature空引用问题 我正在编写一个使用IHttpActivityFeature的ASP.NET Core 8中间件,在集成测试中用WebHostBuilder创建独立测试服务器,但WebHostBuilder默认未配置IHttpActivityFeature,从HttpContext获取该特性时会抛出空引用异常,找不到启用或添加它的方法。
中间件代码
public class TraceIdMiddleware { private const string TraceIdHeader = "X-Trace-Id"; private readonly RequestDelegate _next; public TraceIdMiddleware(RequestDelegate next) { _next = next; } public Task Invoke(HttpContext context) { context.Response.OnStarting(() => { var activityFeature = context.Features.Get<IHttpActivityFeature>(); var traceId = activityFeature.Activity.TraceId.ToString(); context.Response.Headers.TryAdd(TraceIdHeader, traceId); return Task.CompletedTask; }); return _next(context); } }
测试代码
public class WhenMakingAnHttpRequest { [Fact] public async Task ItShouldAddTheTraceIdHeader() { var builder = new WebHostBuilder() .Configure(applicationBuilder => { applicationBuilder .UseTraceId() .Map("/trace-id", app => { app.Run(async context => { await context.Response.WriteAsync("Testing TraceId Middleware"); }); }); }); using var server = new TestServer(builder); using var client = server.CreateClient(); var response = await client.GetAsync("/trace-id"); response.Headers .Should().ContainKey("X-Trace-Id").WhoseValue .Should().NotBeNullOrEmpty(); } }
解决方案
IHttpActivityFeature由ASP.NET Core的诊断系统提供,默认极简配置的WebHostBuilder未包含相关服务和中间件,需要手动添加:
1. 配置测试服务器的服务与中间件
修改测试代码中的WebHostBuilder,添加诊断服务和路由中间件(路由中间件会触发Activity创建,自动注入IHttpActivityFeature):
public class WhenMakingAnHttpRequest { [Fact] public async Task ItShouldAddTheTraceIdHeader() { var builder = new WebHostBuilder() .ConfigureServices(services => { // 注册诊断相关服务 services.AddDiagnostics(); services.AddHttpContextAccessor(); }) .Configure(applicationBuilder => { applicationBuilder // 添加路由中间件,触发Activity创建 .UseRouting() .UseTraceId() .Map("/trace-id", app => { app.Run(async context => { await context.Response.WriteAsync("Testing TraceId Middleware"); }); }) // 启用端点路由完成配置 .UseEndpoints(endpoints => {}); }); using var server = new TestServer(builder); using var client = server.CreateClient(); var response = await client.GetAsync("/trace-id"); response.Headers .Should().ContainKey("X-Trace-Id").WhoseValue .Should().NotBeNullOrEmpty(); } }
2. 优化中间件健壮性(可选但推荐)
为避免生产环境中因缺失IHttpActivityFeature导致崩溃,在中间件中添加空值判断,并提供默认TraceId生成逻辑:
public class TraceIdMiddleware { private const string TraceIdHeader = "X-Trace-Id"; private readonly RequestDelegate _next; public TraceIdMiddleware(RequestDelegate next) { _next = next; } public Task Invoke(HttpContext context) { context.Response.OnStarting(() => { var activityFeature = context.Features.Get<IHttpActivityFeature>(); string traceId; if (activityFeature?.Activity != null) { traceId = activityFeature.Activity.TraceId.ToString(); } else { // 生成默认TraceId traceId = Guid.NewGuid().ToString("N"); } context.Response.Headers.TryAdd(TraceIdHeader, traceId); return Task.CompletedTask; }); return _next(context); } }
内容的提问来源于stack exchange,提问作者David Keaveny
相关产品推荐
相关产品推荐

