当前位置:网站首页>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 :
DependencyInjectionTestFrameworkSource 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); } }}
StarpupLoaderSource 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]所创,转载请带上原文链接,感谢
边栏推荐
- CPP (1) installation of cmake
- Web安全(一)---浏览器同源策略
- 14000 word distributed transaction principle analysis, master all of them, are you afraid of being asked in the interview?
- 数据库基本操作
- Design pattern of facade and mediator
- Share several vs Code plug-ins I use everyday
- Got timeout reading communication packets解决方法
- Web安全(三)---CSRF攻击
- On hiz buffer
- Big data algorithm - bloon filter
猜你喜欢

不懂数据库索引的底层原理?那是因为你心里没点b树

laravel8更新之维护模式改进

一万四千字分布式事务原理解析,全部掌握你还怕面试被问?

【解决方案】分布式定时任务解决方案

Principles of websocket + probuf

什么都2020了,LINQ查询你还在用表达式树
![[C + + learning notes] how about the simple use of the C + + standard library STD:: thread?](/img/3e/3e7bc16c04d0d0ea953e2f739137d3.jpg)
[C + + learning notes] how about the simple use of the C + + standard library STD:: thread?

Code Review Best Practices

面部识别:攻击类型和反欺骗技术

How to learn technology efficiently
随机推荐
go wire 依赖注入入门
websocket+probuf.原理篇
Adobe Lightroom / LR 2021 software installation package (with installation tutorial)
C language I blog assignment 03
Recommend suicide, openai warns: gpt-3 is too risky for medical purposes
How did I lose control of the team?
Principles of websocket + probuf
洞察——风格注意力网络(SANet)在任意风格迁移中的应用
Web Security (4) -- XSS attack
Awk implements SQL like join operation
密码学-尚硅谷
Practice of Xiaoxiong school development board: real equipment access of smart street lamp sandbox experiment
Getting started with go wire dependency injection
Web安全(二)---跨域资源共享
How Facebook open source framework simplifies pytorch experiment
Implementation of multi GPU distributed training with horovod in Amazon sagemaker pipeline mode
一万四千字分布式事务原理解析,全部掌握你还怕面试被问?
Data transmission of asynchronous serial communication controlled by group bus communication
Do not understand the underlying principle of database index? That's because you don't have a B tree in your heart
状态压缩:对动态规划进行降维打击