当前位置:网站首页>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]所创,转载请带上原文链接,感谢
边栏推荐
- WPF 关于绘图个人总结
- 计组-总线通信控制之异步串行通信的数据传输
- Recommend suicide, openai warns: gpt-3 is too risky for medical purposes
- What do you think of the most controversial programming ideas?
- C++在C的基础上改进了哪些细节
- 密码学-尚硅谷
- 汇编函数mcall systemstack asmcgocall syscall
- Kubernetes服务类型浅析:从概念到实践
- Data transmission of asynchronous serial communication controlled by group bus communication
- 三步一坑五步一雷,高速成长下的技术团队怎么带?
猜你喜欢
Got timeout reading communication packets解决方法
密码学-尚硅谷
See once to understand, graphic single chain table inversion
IDEA-项目未自动生成 .iml 文件
What kind of technical ability should a programmer who has worked for 1-3 years? How to improve?
来自不同行业领域的50多个对象检测数据集
Ac86u KX Online
laravel8更新之维护模式改进
Let's talk about the locks in the database
Data transmission of asynchronous serial communication controlled by group bus communication
随机推荐
Data transmission of asynchronous serial communication controlled by group bus communication
go wire 依赖注入入门
C language I blog assignment 03
使用 Xunit.DependencyInjection 改造测试项目
数据库基本操作
It's time to end bertology
WPF personal summary on drawing
Thinkphp6中where条件中字段与字段比较条件的写法
状态压缩:对动态规划进行降维打击
「混合云」会是云计算的下一个战场吗?
sed之查找替换
Adobe media encoder / me 2021 software installation package (with installation tutorial)
一万四千字分布式事务原理解析,全部掌握你还怕面试被问?
洞察——风格注意力网络(SANet)在任意风格迁移中的应用
工作1-3年的程序员,应该具备怎么样的技术能力?该如何提升?
【C++学习笔记】C++ 标准库 std::thread 的简单使用,一文搞定还不简单?
【原创】ARM平台内存和cache对xenomai实时性的影响
Let's talk about the locks in the database
Get started, GIT
Deep into web workers (1)