当前位置:网站首页>use Xunit.DependencyInjection Transformation test project
use Xunit.DependencyInjection Transformation test project
2020-11-07 21:03:00 【Irving the procedural ape】
Use Xunit.DependencyInjection
Transformation test project
Intro
This article has been delayed for a long time , It has been introduced before Xunit.DependencyInjection
This project , This project was written by a master Xunit
Based on Microsoft GenericHost and An extension library for dependency injection implementation , It can make it easier for you to implement dependency injection in test projects , And I think another good point is that it can better control the operation process , For example, many initialization operations are done before starting the test , Better process control .
Recently, most of our company's testing projects are based on Xunit.DependencyInjection
Transformed , The effect is very good .
Recently, I started my test project manually from the original one Web Host It's based on Xunit.DepdencyInjection
To use , At the same time, it is also preparing for the update of integration test of a project of our company , It's delicious to use ~
I think Xunit.DependencyInjection
Solved my two big pain points , One is that dependency injection code doesn't write well , One is a simpler process control process , Here is a general introduction to
XUnit.DependencyInjection
Workflow
Xunit.DepdencyInjection
The main process is DependencyInjectionTestFramework in , See https://github.com/pengweiqhca/Xunit.DependencyInjection/blob/7.0/Xunit.DependencyInjection/DependencyInjectionTestFramework.cs
First of all, I will try to find the... In the project Startup
, This Startup
Very similar to asp.net core Medium Startup
, Almost exactly , It's just a little different , Startup
Dependency injection is not supported , Can not be like asp.net core Put in a like that IConfiguration
Object to get the configuration , besides , and asp.net core Of Startup
Have the same experience , If you can't find this Startup
There are no services or special configurations that need dependency injection , Use it directly Xunit
The original XunitTestFrameworkExecutor
, If you find it Startup
From Startup
Configure in the agreed method Host
, Registration service and initialization configuration process , Finally using DependencyInjectionTestFrameworkExecutor
Carry out our test case.
The source code parsing
The source code uses C#8 Some of the new grammar of , The code is very simple , The following code uses nullable reference types :
DependencyInjectionTestFramework
Source code
public sealed class DependencyInjectionTestFramework : XunitTestFramework{ public DependencyInjectionTestFramework(IMessageSink messageSink) : base(messageSink) { } protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) { IHost? host = null; try { // obtain Startup example var startup = StartupLoader.CreateStartup(StartupLoader.GetStartupType(assemblyName)); if (startup == null) return new XunitTestFrameworkExecutor(assemblyName, SourceInformationProvider, DiagnosticMessageSink); // establish HostBuilder var hostBuilder = StartupLoader.CreateHostBuilder(startup, assemblyName) ?? new HostBuilder().ConfigureHostConfiguration(builder => builder.AddInMemoryCollection(new Dictionary<string, string> { { HostDefaults.ApplicationKey, assemblyName.Name } })); // call Startup Medium ConfigureHost Method configuration Host StartupLoader.ConfigureHost(hostBuilder, startup); // call Startup Medium ConfigureServices Method register service StartupLoader.ConfigureServices(hostBuilder, startup); // Register default service , structure Host host = hostBuilder.ConfigureServices(services => services .AddSingleton(DiagnosticMessageSink) .TryAddSingleton<ITestOutputHelperAccessor, TestOutputHelperAccessor>()) .Build(); // call Startup Medium Configure Method to initialize StartupLoader.Configure(host.Services, startup); // return testcase executor, Ready to start running test cases return new DependencyInjectionTestFrameworkExecutor(host, null, assemblyName, SourceInformationProvider, DiagnosticMessageSink); } catch (Exception e) { return new DependencyInjectionTestFrameworkExecutor(host, e, assemblyName, SourceInformationProvider, DiagnosticMessageSink); } }}
StarpupLoader
Source code
public static Type? GetStartupType(AssemblyName assemblyName){ var assembly = Assembly.Load(assemblyName); var attr = assembly.GetCustomAttribute<StartupTypeAttribute>(); if (attr == null) return assembly.GetType($"{assemblyName.Name}.Startup"); if (attr.AssemblyName != null) assembly = Assembly.Load(attr.AssemblyName); return assembly.GetType(attr.TypeName) ?? throw new InvalidOperationException($"Can't load type {attr.TypeName} in '{assembly.FullName}'");}public static object? CreateStartup(Type? startupType){ if (startupType == null) return null; var ctors = startupType.GetConstructors(); if (ctors.Length != 1 || ctors[0].GetParameters().Length != 0) throw new InvalidOperationException($"'{startupType.FullName}' must have a single public constructor and the constructor without parameters."); return Activator.CreateInstance(startupType);}public static IHostBuilder? CreateHostBuilder(object startup, AssemblyName assemblyName){ var method = FindMethod(startup.GetType(), nameof(CreateHostBuilder), typeof(IHostBuilder)); if (method == null) return null; var parameters = method.GetParameters(); if (parameters.Length == 0) return (IHostBuilder)method.Invoke(startup, Array.Empty<object>()); if (parameters.Length > 1 || parameters[0].ParameterType != typeof(AssemblyName)) throw new InvalidOperationException($"The '{method.Name}' method of startup type '{startup.GetType().FullName}' must without parameters or have the single 'AssemblyName' parameter."); return (IHostBuilder)method.Invoke(startup, new object[] { assemblyName });}public static void ConfigureHost(IHostBuilder builder, object startup){ var method = FindMethod(startup.GetType(), nameof(ConfigureHost)); if (method == null) return; var parameters = method.GetParameters(); if (parameters.Length != 1 || parameters[0].ParameterType != typeof(IHostBuilder)) throw new InvalidOperationException($"The '{method.Name}' method of startup type '{startup.GetType().FullName}' must have the single 'IHostBuilder' parameter."); method.Invoke(startup, new object[] { builder });}public static void ConfigureServices(IHostBuilder builder, object startup){ var method = FindMethod(startup.GetType(), nameof(ConfigureServices)); if (method == null) return; var parameters = method.GetParameters(); builder.ConfigureServices(parameters.Length switch { 1 when parameters[0].ParameterType == typeof(IServiceCollection) => (.........
版权声明
本文为[Irving the procedural ape]所创,转载请带上原文链接,感谢
边栏推荐
- 年薪90万程序员不如月入3800公务员?安稳与高收入,到底如何选择?
- Animation techniques and details you may not know
- awk实现类sql的join操作
- 一万四千字分布式事务原理解析,全部掌握你还怕面试被问?
- C language I blog assignment 03
- sed之查找替换
- Three steps, one pit, five steps and one thunder, how to lead the technical team under the rapid growth?
- 爆一个VS2015 Update1更新带来的编译BUG【已有解决方案】
- High concurrency in ngnix cluster
- Cpp(四) Boost安装及基本使用 for Mac
猜你喜欢
More than 50 object detection datasets from different industries
The CPU does this without the memory
Everything is 2020, LINQ query you are still using expression tree
Count the frequency of letters in text (case insensitive)
【C++学习笔记】C++ 标准库 std::thread 的简单使用,一文搞定还不简单?
delphi10的rest.json与system.json的踩坑
构造请求日志分析系统
Ubuntu下搜狗输入法的下载安装及配置
一万四千字分布式事务原理解析,全部掌握你还怕面试被问?
On hiz buffer
随机推荐
Facebook开源框架如何简化 PyTorch 实验
Big data algorithm - bloon filter
How to think in the way of computer
Practice of Xiaoxiong school development board: real equipment access of smart street lamp sandbox experiment
分享几个我日常使用的VS Code插件
【解决方案】分布式定时任务解决方案
Kylin on Kubernetes 在 eBay 的实践
如何以计算机的方式去思考
The emergence and significance of micro service
Assembly function MCALL systemstack asmcgocal system call
建议患者自杀,OpenAI警告:GPT-3用于医疗目的风险太高
【原创】ARM平台内存和cache对xenomai实时性的影响
Recommend suicide, openai warns: gpt-3 is too risky for medical purposes
CPP (1) installation of cmake
Cpp(四) Boost安装及基本使用 for Mac
京淘项目day09
How did I lose control of the team?
凯撒密码实现
Git代码提交操作,以及git push提示failed to push some refs'XXX'
ROS learning: remote start ROS node