You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用WebApplicationFactory测试带Autofac DI的CoreWCF端点?

优化CoreWCF集成测试中TestServer的IServerAddressesFeature配置(替代反射方案)

问题背景

使用Autofac作为DI容器的CoreWCF项目,通过自定义WebApplicationFactory编写集成测试时,发现TestServer未配置IServerAddressesFeature,导致CoreWCF的ApplyConfiguration执行失败。当前通过反射修改TestServer的私有字段解决,但依赖内部实现,稳定性不足。

更优解决方案

利用TestServer公开的Features属性直接配置IServerAddressesFeature,无需反射。具体修改WcfWebApplicationFactory的CreateHost方法,在Host创建完成后直接操作TestServer的特性集合:

优化后的完整代码

/// Enables in-memory integration testing for CoreWCF (outside-in testing via <see cref="HttpClient"/>).
///
/// Use these tests to exercise the entire HTTP stack, rather than create in-process ServiceModel channels.
/// </summary>
/// <typeparam name="TStartup"></typeparam>
public class WcfWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    private ILifetimeScope _container;

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestContainer<ContainerBuilder>(container =>
        {
            container.RegisterBuildCallback(BuildCallback);
        });
    }

    private void BuildCallback(ILifetimeScope obj)
    {
        _container = obj;
    }

    protected override IHost CreateHost(IHostBuilder builder)
    {
        builder.UseServiceProviderFactory(new CustomServiceProviderFactory());
        var host = base.CreateHost(builder);
        
        // 配置TestServer的IServerAddressesFeature,无需反射
        var testServer = host.Services.GetRequiredService<IServer>() as TestServer;
        if (testServer != null)
        {
            var addressesFeature = testServer.Features.Get<IServerAddressesFeature>() ?? new ServerAddressesFeature();
            addressesFeature.Addresses.Add(ClientOptions.BaseAddress.ToString());
            testServer.Features.Set(addressesFeature);
        }
        
        return host;
    }
}

/// <summary>
/// Handles Autofac container integration with ASP.NET Core test pipeline
/// </summary>
public class CustomServiceProviderFactory : IServiceProviderFactory<ContainerBuilder>
{
    private readonly AutofacServiceProviderFactory _wrapped = new AutofacServiceProviderFactory();
    private IServiceCollection _services;

    public ContainerBuilder CreateBuilder(IServiceCollection services)
    {
        _services = services;
        return _wrapped.CreateBuilder(services);
    }

    public IServiceProvider CreateServiceProvider(ContainerBuilder containerBuilder)
    {
        var sp = _services.BuildServiceProvider();
#pragma warning disable CS0612 // Type or member is obsolete
        var filters = sp.GetRequiredService<IEnumerable<IStartupConfigureContainerFilter<ContainerBuilder>>>();
#pragma warning restore CS0612 // Type or member is obsolete
        foreach (var filter in filters)
        {
            filter.ConfigureContainer(b => { })(containerBuilder);
        }

        return _wrapped.CreateServiceProvider(containerBuilder);
    }
}

方案优势

  1. 避免反射依赖:不再依赖TestServer的私有字段,利用公开API操作,代码稳定性更高,不会因框架内部实现变更而失效。
  2. 逻辑更清晰:将特性配置逻辑放在CreateHost阶段,符合WebApplicationFactory的生命周期流程,代码可读性更强。
  3. 职责更单一:移除原代码中反射相关的复杂逻辑,CustomServiceProviderFactory仅专注于Autofac容器与ASP.NET Core测试管道的集成。

内容的提问来源于stack exchange,提问作者Guy Pender

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 19:09:28