在WebApplicationFactory端到端测试中,如何注销AddHttpClient<ISendGridClient, SendGridClient>?
如何注销通过AddHttpClient<ISendGridClient, SendGridClient>注册的服务?
问题描述
我正在使用WebApplicationFactory进行端到端测试,需要在测试宿主应用中注销以下服务注册:
services.AddHttpClient<ISendGridClient, SendGridClient>();
之后我会按如下方式重新注册:
services .AddHttpClient<ISendGridClient, SendGridClient>() .ConfigurePrimaryHttpMessageHandler(_ => MockSendGridHttpMessageHandler);
请问如何注销通过上述AddHttpClient<ISendGridClient, SendGridClient>添加的服务?
解决方案
ASP.NET Core的DI容器没有提供直接"注销"服务的API,但可以通过移除原有注册项后重新添加的方式实现替换:
方法1:批量移除关联注册
遍历IServiceCollection,移除所有与ISendGridClient及对应HttpClient相关的注册,再重新添加自定义配置的HttpClient:
// 在WebApplicationFactory的ConfigureServices回调中 var targetRegistrations = services.Where(descriptor => descriptor.ServiceType == typeof(ISendGridClient) || (descriptor.ServiceType == typeof(HttpClient) && descriptor.Key?.ToString() == typeof(SendGridClient).FullName)) .ToList(); foreach (var registration in targetRegistrations) { services.Remove(registration); } // 重新注册带Mock处理器的HttpClient services .AddHttpClient<ISendGridClient, SendGridClient>() .ConfigurePrimaryHttpMessageHandler(_ => MockSendGridHttpMessageHandler);
方法2:精准替换目标服务
直接定位ISendGridClient的服务描述符并移除,再重新注册:
var sendGridDescriptor = services.FirstOrDefault(d => d.ServiceType == typeof(ISendGridClient)); if (sendGridDescriptor != null) { services.Remove(sendGridDescriptor); } // 重新注册自定义HttpClient services.AddHttpClient<ISendGridClient, SendGridClient>() .ConfigurePrimaryHttpMessageHandler(_ => MockSendGridHttpMessageHandler);
在WebApplicationFactory中集成
可以通过重写ConfigureWebHost方法来封装上述逻辑,供测试复用:
public class TestWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class { protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.ConfigureServices(services => { // 清理原有SendGridClient相关注册 var registrationsToRemove = services.Where(d => d.ServiceType == typeof(ISendGridClient) || (d.ServiceType == typeof(HttpClient) && d.Key?.ToString() == typeof(SendGridClient).FullName)) .ToList(); foreach (var descriptor in registrationsToRemove) { services.Remove(descriptor); } // 注册带Mock处理器的SendGridClient services.AddHttpClient<ISendGridClient, SendGridClient>() .ConfigurePrimaryHttpMessageHandler(_ => MockSendGridHttpMessageHandler); }); } }
内容的提问来源于stack exchange,提问作者Peter Morris
相关产品推荐
相关产品推荐

