Xunit.DependencyInjection 7.0 發布了
Intro
上次我們已經介紹過一次大師的 Xunit.DependencyInjection https://www.cnblogs.com/weihanli/p/xuint-dependency-injection.html ,最近大師完成了 7.0 的重構並且已經正式發布,已經可以直接安裝使用了
7.0 為我們帶來了更好的編程體驗,在 6.x 的版本中,我們的 Startup 需要繼承於 DependencyInjectionTestFramework 而且需要設置一個 assembly attribute,這在 7.0 中都不需要了,下面我們來看看有了哪些變化
Startup 的變化
首先來看大師給出的 diff
-[assembly: TestFramework("Your.Test.Project.Startup", "Your.Test.Project")]
namespace Your.Test.Project
{
- public class Startup : DependencyInjectionTestFramework
+ public class Startup
{
- public Startup(IMessageSink messageSink) : base(messageSink) { }
- protected void ConfigureServices(IServiceCollection services)
+ public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IDependency, DependencyClass>();
}
- protected override IHostBuilder CreateHostBuilder() =>
- base.CreateHostBuilder(assemblyName)
- .ConfigureServices(ConfigureServices);
- protected override void Configure(IServiceProvider provider)
+ public void Configure(IServiceProvider provider)
}
}
- 移除了
TestFrameworkassembly attribute - 不再需要繼承於
DependencyInjectionTestFramework - 也因為上面的不需要繼承,所以原本要
override的方法可以不override了,原來是protected的方法現在需要改成public
這樣改了之后首先我們在使用的時候無需知道 DependencyInjectionTestFramework 的存在了,而且可以更符合 asp.net core Startup 的使用習慣,可以屏蔽掉很多實現細節,用戶只需要在 Startup 注冊自己的邏輯即可,更為專注於自己的邏輯而無需關心框架所做的事情
新的 Startup 解析
我把上一篇文章寫的示例用升級到了新的版本,下面是更新后的示例代碼
namespace XUnitDependencyInjectionSample
{
public class Startup
{
// 自定義 HostBuilder ,可以沒有這個方法,沒有這個方法會使用默認的 hostBuilder,通常直接使用 `ConfigureHost` 應該就夠用了
// public IHostBuilder CreateHostBuilder()
// {
// return new HostBuilder()
// .ConfigureAppConfiguration(builder =>
// {
// // 注冊配置
// builder
// .AddInMemoryCollection(new Dictionary<string, string>()
// {
// {"UserName", "Alice"}
// })
// .AddJsonFile("appsettings.json")
// ;
// })
// .ConfigureServices((context, services) =>
// {
// // 注冊自定義服務
// services.AddSingleton<IIdGenerator, GuidIdGenerator>();
// if (context.Configuration.GetAppSetting<bool>("XxxEnabled"))
// {
// services.AddSingleton<IUserIdProvider, EnvironmentUserIdProvider>();
// }
// })
// ;
// }
// 自定義 host 構建
public void ConfigureHost(IHostBuilder hostBuilder)
{
hostBuilder
.ConfigureAppConfiguration(builder =>
{
// 注冊配置
builder
.AddInMemoryCollection(new Dictionary<string, string>()
{
{"UserName", "Alice"}
})
.AddJsonFile("appsettings.json")
;
})
.ConfigureServices((context, services) =>
{
// 注冊自定義服務
services.AddSingleton<IIdGenerator, GuidIdGenerator>();
if (context.Configuration.GetAppSetting<bool>("XxxEnabled"))
{
services.AddSingleton<IUserIdProvider, EnvironmentUserIdProvider>();
}
})
;
}
// 支持的形式:
// ConfigureServices(IServiceCollection services)
// ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
{
services.TryAddSingleton<CustomService>();
}
// 可以添加要用到的方法參數,會自動從注冊的服務中獲取服務實例,類似於 asp.net core 里 Configure 方法
public void Configure(IServiceProvider applicationServices, IIdGenerator idGenerator)
{
// 有一些測試數據要初始化可以放在這里
// InitData();
}
}
}
在新的版本中 Startup 和 asp.net core 里的 Startup 更加相像了,
會多一個 CreateHostBuilder/ConfigureHost(IHostBuilder) 的方法,允許用戶自定義 Host 的構建,也可以沒有這個方法
ConfigureServices 方法允許用戶增加 HostBuilderContext 作為參數,可以通過 hostBuilderContext 來獲取配置信息,也可以在 CreateHostBuilder/ConfigureHost(IHostBuilder) 里注冊也是一樣的
注冊配置/服務和 asp.net core 里一模一樣,有數據或配置需要在項目啟動時初始化的,可以放在 Configure 方法做,有點類似於 asp.net core 里 Startup 中的 Configure 方法,可以將需要的服務作為方法參數,執行時會自動從注冊的服務中獲取
Startup 的尋找方法
默認的 Startup 通常是 ProjectName.Startup,通常在項目根目錄下創建一個 Startup 是不需要配置的,如果不是或不起作用,可以參考下面 Startup 的尋找規則
如果要使用一個特別的 Startup, 你可以通過在項目文件的 PropertyGroup 部分定義 XunitStartupAssembly 和 XunitStartupFullName,具體規則如下
<Project>
<PropertyGroup>
<XunitStartupAssembly>Abc</XunitStartupAssembly>
<XunitStartupFullName>Xyz</XunitStartupFullName>
</PropertyGroup>
</Project>
| XunitStartupAssembly | XunitStartupFullName | Startup |
|---|---|---|
| Your.Test.Project.Startup, Your.Test.Project | ||
| Abc | Abc.Startup, Abc | |
| Xyz | Xyz, Your.Test.Project | |
| Abc | Xyz | Xyz, Abc |
More
除了上面的 Startup 的改動之外,新版本還支持了 xunit 中 fixture 的依賴注入,似乎是由一個外國小哥提的 PR, 詳見:https://github.com/pengweiqhca/Xunit.DependencyInjection/pull/21
有了這個神器,在測試代碼中使用依賴注入要方便很多了,還沒有用起來的可以准備上手了~~
