ASP.NET Core集成测试中如何自定义WebApplicationFactory设置固定RemoteIpAddress
可以直接通过扩展WebApplicationFactory的请求管道实现固定IP设置,不需要额外封装服务做Mock,实现方式如下:
方案1:直接在测试代码中inline配置
直接在创建WebApplicationFactory时注入重写IP的中间件,适合单次测试场景:
var expectedIp = IPAddress.Parse("192.168.1.123"); var factory = new WebApplicationFactory<Startup>() .WithWebHostBuilder(builder => { builder.ConfigureServices(services => { // 若原项目已注册IHttpContextAccessor可省略此行 services.AddHttpContextAccessor(); }); builder.Configure(app => { // 优先级最高的中间件,所有请求进来先重写远程IP app.Use(async (context, next) => { context.Connection.RemoteIpAddress = expectedIp; await next.Invoke(); }); // 注册原有应用的中间件管道 // 若你使用的是ASP.NET Core 6+的顶层语句启动模式,替换为你实际的启动配置 var startup = new Startup(builder.GetSetting("Environment")); startup.Configure(app, builder.Services.BuildServiceProvider()); }); }); using var client = factory.CreateClient(); // 注意:原测试代码中GetAsync的Uri参数存在语法错误,直接传相对路径即可 var response = await client.GetAsync("/test"); var actualIp = await response.Content.ReadAsStringAsync(); // 可添加断言验证结果 // Assert.Equal(expectedIp.ToString(), actualIp);
方案2:封装自定义WebApplicationFactory复用
如果需要在多个测试用例中复用固定IP配置,可以自定义工厂类:
public class FixedIpWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class { // 对外暴露可配置的固定IP属性 public IPAddress RemoteIpAddress { get; set; } = IPAddress.Loopback; protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.ConfigureServices(services => { services.AddHttpContextAccessor(); }); builder.Configure(app => { app.Use(async (context, next) => { context.Connection.RemoteIpAddress = RemoteIpAddress; await next.Invoke(); }); // 加载原有应用的启动配置 var startup = ActivatorUtilities.CreateInstance<Startup>( app.ApplicationServices, builder.GetSetting("Environment") ); startup.Configure(app, app.ApplicationServices); }); } }
测试时的调用代码:
var factory = new FixedIpWebApplicationFactory<Startup>() { RemoteIpAddress = IPAddress.Parse("192.168.1.123") }; using var client = factory.CreateClient(); // 后续请求逻辑同上
实现原理
WebApplicationFactory启动的测试服务端,所有通过CreateClient发出的请求都会经过你配置的中间件管道。我们在所有业务逻辑执行前就把Connection.RemoteIpAddress覆盖为自定义的固定值,后续控制器通过IHttpContextAccessor读取到的就是我们预设的IP,完全贴合真实运行场景,比Mock服务的方式更符合集成测试的要求。
注意:如果你的项目本身配置了ForwardedHeaders中间件处理反向代理转发的IP,需要将上述重写IP的中间件放在ForwardedHeaders中间件之后执行,避免被转发头覆盖自定义IP。
内容的提问来源于stack exchange,提问作者Józef Podlecki
相关产品推荐
相关产品推荐

