namespace SemanticKernelStudy.Test; /// /// xUnit:依赖注入框架(Xunit.DependencyInjection)的启动类 /// 1、执行顺序按照方法代码书写顺序执行(BuildHost有点特殊 /// 2、两种风格任选其一即可:同时存在,则HostApplicationBuilder风格优先,Startup风格的方法会被忽略 /// 3、两种风格都支持Configure方法:都会在最后执行 /// 4、一次测试中,只执行一次(无论一次测试执行了多少个单元测试) /// public class Startup { #region HostApplicationBuilder 风格 /* /// /// 必须:主配置方法 /// 1、用本方法区分两种风格:本方法优先,如果存在本方法,则忽略Startup风格的方法 /// /// public void ConfigureHostApplicationBuilder(IHostApplicationBuilder hostApplicationBuilder) { } /// /// 可选:生成IHost主机,只在异常时需要此方法 /// 在程序因找不到此方法签名异常时,只需添加本方法,并调用 hostApplicationBuilder.Build() 即可构建主机。 /// /// /// public IHost BuildHostApplicationBuilder(HostApplicationBuilder hostApplicationBuilder) { return hostApplicationBuilder.Build(); } */ #endregion #region Startup 风格 /// /// 可选:创建HostBuilder /// 主要用于Minimal API场景,需导入Xunit.DependencyInjection.AspNetCoreTesting包 /// /// public IHostBuilder CreateHostBuilder(System.Reflection.AssemblyName assemblyName) { // minimal API testing, see details: https://github.com/pengweiqhca/Xunit.DependencyInjection#minimalapi // return MinimalApiHostBuilderFactory.GetHostBuilder(); //通用方式:可以省略本方法 IHostBuilder hostBuilder = new HostBuilder(); //IHostBuilder hostBuilder = Host.CreateDefaultBuilder(); //注入(先执行):主机 IConfiguration hostBuilder.ConfigureHostConfiguration(config => { //config.AddJsonFile($"{assemblyName}.json"); }); //注入(后执行):应用 IConfiguration hostBuilder.ConfigureAppConfiguration((context, builder) => { //builder.AddEnvironmentVariables(); }); //设置日志 hostBuilder.ConfigureLogging((context, builder) => { }); return hostBuilder; } /// /// 可选:配置Host主机 /// /// public void ConfigureHost(IHostBuilder hostBuilder) { hostBuilder.ConfigureLogging(config => { //清除日志设置 //config.ClearProviders(); //集成 OpenTelemetry Logger config.AddOpenTelemetry(config => { config .AddConsoleExporter() .AddOtlpExporter(config => { config.Endpoint = new Uri("http://localhost:4317/"); }); }); //将 Microsoft.Extensions.Logging 日志写入到 ITestOutputHelper //需要导入 Microsoft.Extensions.Logging、Xunit.DependencyInjection.Logging包,设置后统一使用ILogger(不再单独使用 ITestOutputHelper) config .AddXunitOutput() .SetMinimumLevel(LogLevel.Trace); }); //集成 OpenTelemetry Tracer TracerProviderBuilder builder = Sdk.CreateTracerProviderBuilder(); builder .SetResourceBuilder ( ResourceBuilder .CreateDefault() .AddService("Xunit.DependencyInjectionService=========================================") ) .AddSource("Xunit.DependencyInjection") .AddHttpClientInstrumentation() .AddConsoleExporter() .AddOtlpExporter(config => { config.Endpoint = new Uri("http://localhost:4317"); }) .AddZipkinExporter(config => { config.Endpoint = new Uri("http://localhost:9411/api/v2/spans"); }) ; } /* 异常时启用 /// /// 可选:构建Host主机 /// 如果找不到此方法签名,使用此方法即可构建主机 /// 注意:没有异常时,不需要此方法 /// /// /// public IHost BuildHost(IHostBuilder hostBuilder) { //注意:执行Build 方法之前(此时还没有创建IHost对象),先执行 ConfigureServices 方法 IHost host = hostBuilder.Build(); //注意:ConfigureServices方法执行后,回返回此处继续执行 return host; } */ /// /// 必须:配置IoC容器服务 /// 注意:如果有BuildHost方法,则执行本方法后,回返回 BuildHost 方法继续执行 /// /// 必须 /// 可选 /// public void ConfigureServices(IServiceCollection services, HostBuilderContext context) { //将 Microsoft.Extensions.Logging 日志写入到 ITestOutputHelper //需要导入 Microsoft.Extensions.Logging、Xunit.DependencyInjection.Logging包,设置后统一使用ILogger(不再单独使用 ITestOutputHelper) //services.AddLogging(configLog => //{ // configLog // .AddOpenTelemetry(options => // { // options // .AddConsoleExporter() // .AddOtlpExporter(config => // { // config.Endpoint = new Uri("http://localhost:4317/"); // }); // }) // .AddXunitOutput() // .SetMinimumLevel(LogLevel.Trace); //}); //也可以直接使用 //configLog.AddXunitOutput().SetMinimumLevel(LogLevel.Trace); JsonSerializerOptions serializerOption = new JsonSerializerOptions() { // 设置编码器,允许非ASCII字符直接输出 Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, // 可选:设置缩进,使输出更易读 WriteIndented = true }; services.AddKeyedSingleton("NiceJsonOption", serializerOption); } #endregion /// /// 可选:两种风格都支持的方法(最后执行) /// 参数:已经注册过的对象都可以,默认情况下,IServiceCollection 未注册 /// 注意:默认的,从参数中不能获取 IServiceCollection,也就不能进行IoC注册;也就启动的末尾(全局启动的结尾,不是单元测试方法的结尾),做些收尾的事. /// /// 可选的 IServiceProvider public void Configure ( IHost host, IServiceProvider applicationServices, HostBuilderContext hostBuilderContext, IHostEnvironment env, IConfiguration configuration, ITestOutputHelperAccessor helperAccessor ) { //启动后:业务逻辑 } }