WebApplicationFactory创建的测试应用是否监听主机真实端口?
核心原因
WebApplicationFactory 默认走内存 TestServer 承载应用,CreateClient() 生成的客户端直接和内存中的服务做进程内请求转发,完全绕过真实网络栈,所以不管你填什么URL,都不会发到真实的网络端口。你之前配置Kestrel端口不生效,是因为默认场景下TestServer会直接替换Kestrel作为服务宿主,根本不会启动Kestrel,自然不会绑定任何真实端口。
优先方案(无需绑定真实端口,性能最优)
直接在两个客户端之间共享同一个 CookieContainer,测试客户端从待测试接口拿到的Cookie会自动存入容器,请求5555端口服务的客户端会自动携带匹配的Cookie,不需要手动解析、复制Cookie值。
// 初始化跨客户端共享的Cookie容器 var sharedCookieContainer = new CookieContainer(); // 配置测试客户端,将请求转发给内存TestServer的同时使用共享Cookie容器 var testServerHandler = _webApplicationFactory.Server.CreateHandler(); var testClient = new HttpClient(new HttpClientHandler { UseCookies = true, CookieContainer = sharedCookieContainer, InnerHandler = testServerHandler // 把请求转给内存TestServer处理 }) { BaseAddress = new Uri("http://localhost") }; // 配置请求5555端口服务的客户端,共用同一个Cookie容器 var localServiceClient = new HttpClient(new HttpClientHandler { UseCookies = true, CookieContainer = sharedCookieContainer }) { BaseAddress = new Uri("http://localhost:5555") };
使用时先通过testClient调用待测试的接口,接口返回的Set-Cookie响应头会被自动写入共享Cookie容器,后续用localServiceClient调用5555端口的服务时,符合域名、路径规则的Cookie会被自动附加到请求头中。
注意:Cookie的域名、路径匹配规则会自动生效,测试客户端从接口拿到的
localhost域名Cookie,在请求localhost:5555时会被自动携带,不需要手动修改Cookie的域名属性。
这个方案全程使用内存TestServer,不占用真实端口,无端口冲突问题,测试启动速度最快,支持并行测试,覆盖90%以上的集成测试场景。
备选方案(需要真实端口监听时使用)
如果你的场景必须让待测试应用绑定真实主机端口(比如有第三方组件无法修改,必须走真实网络请求),可以手动关闭WebApplicationFactory默认注入的TestServer,让Kestrel正常启动绑定指定端口:
public class RealPortFactory : WebApplicationFactory<Program> { protected override void ConfigureWebHost(IWebHostBuilder builder) { // 关键配置:禁用默认的TestServer,让Kestrel作为正常服务器启动 builder.UseSetting("TESTSERVER_DISABLED", "true"); // 配置Kestrel监听指定本地端口,可选择固定端口或者动态获取空闲端口 builder.ConfigureKestrel(options => { options.ListenLocalhost(5099); }); // 其余测试配置(比如替换服务、使用内存数据库等)照常编写 } }
启动该工厂后,待测试应用会真实绑定到localhost:5099,你可以直接创建普通HttpClient分别请求5099端口的待测试应用、5555端口的其他服务,Cookie透传逻辑同样可以通过共享CookieContainer实现。
注意这个方案因为要启动真实Kestrel服务器、绑定端口,启动速度比内存TestServer慢,同时要注意避免端口冲突,不适合高并发并行测试场景。
内容的提问来源于stack exchange,提问作者user606521

