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

.NET Core 2.1与3.1中WebApplicationFactory的ConfigureServices调用顺序问询

Answer

Is this an intentional change?

Yes, this is an intentional breaking change introduced in ASP.NET Core 3.0 (and maintained in 3.1). The ASP.NET Core team adjusted the service configuration order in WebApplicationFactory to align test setup with how production applications handle service registration.

In .NET Core 2.x, your test's ConfigureServices ran before the app's Startup.ConfigureServices, letting you use TryAdd* methods to "pre-register" services that the app would skip. In 3.x+, the order was reversed: the app's Startup.ConfigureServices runs first, followed by test-specific configuration. This ensures test overrides properly match the real host configuration flow your app uses in production.

Why did this change happen?

The core goal was consistency. In ASP.NET Core 3.x production apps, the host builder's configuration runs after the Startup class's ConfigureServices. WebApplicationFactory was updated to mirror this behavior, so tests now reflect the actual service registration order your app follows live.

Solutions for .NET Core 3.1+

Since the app registers services first, you need to replace existing registrations instead of trying to pre-add them. Here are reliable fixes for your scenario:

1. Replace the service descriptor directly

Modify your test's ConfigureServices to swap the existing IHelloService registration:

protected override void ConfigureServices(IServiceCollection services)
{
    services.Replace(ServiceDescriptor.Singleton<IHelloService, CustomHelloService>());
}

This replaces any existing singleton registration of IHelloService with your custom implementation, regardless of order.

2. Remove all existing registrations first

If you want to ensure no leftover registrations remain, clear all instances of the service type before adding your own:

protected override void ConfigureServices(IServiceCollection services)
{
    services.RemoveAll<IHelloService>();
    services.AddSingleton<IHelloService, CustomHelloService>();
}

This is helpful if your app might register multiple implementations of the same interface.

Instead of overriding ConfigureServices in your base class, use ConfigureTestServices directly in the WithWebHostBuilder call. This is the official convention for test-specific service setup in 3.x+:

_factory = new WebApplicationFactory<TStartup>().WithWebHostBuilder(b =>
{
    b.UseSolutionRelativeContentRoot(Path.Combine("src", projectRelativePath))
     .ConfigureTestServices(services =>
     {
         services.Replace(ServiceDescriptor.Singleton<IHelloService, CustomHelloService>());
     });
});

ConfigureTestServices is designed explicitly for test scenarios, making your code more readable and aligned with ASP.NET Core best practices.

Summary

This is not a bug—it's an intentional change to make test behavior match production. The key adjustment is moving from TryAdd* methods (which relied on running first) to using Replace or RemoveAll + Add* to override existing services.

内容的提问来源于stack exchange,提问作者Lukasz Pyrzyk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 23:32:48