Xunit.DependencyInjection 7.0 发布了
Intro
上次我们已经介绍过一次大师的 Xunit.DependencyInjection
在 Xunit 中使用依赖注入 ,最近大师完成了 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)}
}
移除了
TestFramework
assembly attribute不再需要继承于
DependencyInjectionTestFramework
也因为上面的不需要继承,所以原本要
override
的方法可以不override
了,原来是protected
的方法现在需要改成public
新的 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
有了这个神器,在测试代码中使用依赖注入要方便很多了,还没有用起来的可以准备上手了~~
Reference
https://github.com/pengweiqhca/Xunit.DependencyInjection
https://github.com/WeihanLi/SamplesInPractice/tree/master/XUnitDependencyInjectionSample