Net6 Minimal Web API测试中配置覆盖无效,请求解决方案
问题解决:WebApplicationFactory添加的配置在Program中读取为null
问题重现
Program.cs代码
WebApplicationBuilder builder = WebApplication.CreateBuilder(args); string foo = builder.Configuration.GetValue<string>("foo"); // 预期为"bar",实际为null public partial class Program{}
测试项目代码
public class MyWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class { protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.ConfigureAppConfiguration((context, configBuilder) => { configBuilder.AddInMemoryCollection( new Dictionary<string, string?> { ["foo"] = "bar" }); }); } } public class Test { private readonly HttpClient _client; public Test(MyWebApplicationFactory<Program> factory) { _client = factory.WithWebHostBuilder().CreateClient(); } }
配置添加后始终未生效,调试时foo一直是null,核心原因是Program中直接创建builder并读取配置的时机,早于WebApplicationFactory注入配置的时机。
解决方案
方案1:延迟配置读取到服务注入阶段
不要在Program顶级语句中直接读取配置,将读取逻辑移到ConfigureServices中,确保WebApplicationFactory的配置已经生效:
WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // 将配置读取逻辑移到服务注册中,此时配置已被WebApplicationFactory修改 builder.Services.AddSingleton<string>(sp => { var config = sp.GetRequiredService<IConfiguration>(); return config.GetValue<string>("foo") ?? string.Empty; }); var app = builder.Build(); // 后续应用配置代码... public partial class Program{}
方案2:提前在CreateHostBuilder阶段注入配置
重写CreateHostBuilder方法,在宿主构建的早期阶段注入配置,让Program创建builder时能直接获取到:
public class MyWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class { protected override IHostBuilder CreateHostBuilder() { return Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<TStartup>(); // 在此阶段注入配置,早于Program中builder的创建 webBuilder.ConfigureAppConfiguration((context, configBuilder) => { configBuilder.AddInMemoryCollection( new Dictionary<string, string?> { ["foo"] = "bar" }); }); }); } }
原因说明
WebApplication.CreateBuilder(args)会立即初始化一套独立的配置系统,读取默认配置源。而WebApplicationFactory的ConfigureWebHost方法是在宿主构建的后期执行的,此时Program中已经完成了builder的创建和配置读取,所以新增的内存配置不会被包含进去。
通过延迟配置读取或提前注入配置,能让两者的时机对齐,确保测试中添加的配置生效。
内容的提问来源于stack exchange,提问作者Richard Barraclough
相关产品推荐
相关产品推荐

