单元测试环境下WebSocket连接失败返回404错误问题排查
问题原因
- 核心错误:中间件注册顺序不符合ASP.NET Core管道规则
ASP.NET Core请求管道严格按代码书写顺序执行,前序中间件生成响应后,后续中间件不会再处理请求。你当前RunAppAsync方法中,先注册了所有HTTP接口端点(MapGet、业务用例端点、控制器),最后才调用app.UseWebSockets()注册WebSocket中间件。WebSocket升级请求到达后,先被端点路由层处理,因未经过协议升级无法匹配到对应处理逻辑,直接返回404,位于管道末尾的WebSocket中间件根本接触不到请求。 - 测试启动逻辑存在缺陷
你在测试静态构造函数中用_ = Program.RunAppAsync(app)直接丢弃异步启动任务,既不捕获启动异常,也不等待应用完成全量初始化,虽然简单GET请求可能碰巧访问成功,但WebSocket相关端点可能未完成注册就收到请求,也会触发异常。
修复方案
- 调整中间件注册顺序,将WebSocket中间件移到所有端点注册逻辑之前
public static async Task RunAppAsync(WebApplication app) { // WebSocket中间件必须放在所有路由、端点配置之前 app.UseWebSockets(); app.MapGet("/", () => "Gambit.Server.API is running"); app.AddUserUseCases(); app.AddGameUseCases(); app.MapControllers(); await app.RunAsync(); }
- 优化测试服务启动逻辑,等待应用完全启动后再执行测试用例
static async Task<WebApplication> StartTestServer() { ConfigureMocks(); Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "IntegrationTesting"); var app = Program.BuildApp(Array.Empty<string>(), builder => { builder.WebHost.UseSetting("urls", "https://localhost:8080"); }); // 初始化数据库 Configuration = app.Services.GetRequiredService<IConfiguration>(); GameServerOptions = app.Services.GetRequiredService<IOptions<GameServerOptions>>(); var dbContextOptions = app.Services.GetRequiredService<DbContextOptions<ApplicationDbContext>>(); using var dbContext = new ApplicationDbContext(dbContextOptions); dbContext.Database.EnsureDeleted(); dbContext.Database.EnsureCreated(); // 启动服务并等待初始化完成 var runTask = Program.RunAppAsync(app); var lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>(); var startWaiter = new TaskCompletionSource(); lifetime.ApplicationStarted.Register(() => startWaiter.SetResult()); // 设置10秒启动超时,避免无限等待 await startWaiter.Task.WaitAsync(TimeSpan.FromSeconds(10)); HttpClient = new HttpClient { BaseAddress = new Uri("https://localhost:8080") }; return app; }
测试初始化时异步调用该方法等待服务启动完成,测试执行结束后调用app.StopAsync()释放端口资源即可。
调整后WebSocket升级请求会先经过WebSocket中间件完成协议升级,再匹配到/game-server端点返回101切换协议响应,404问题会完全消失。
内容的提问来源于stack exchange,提问作者Peter Morris
相关产品推荐
相关产品推荐

