在 xunit 测试项目中使用依赖注入

在 xunit 测试项目中使用依赖注入

Intro

之前写过几篇 xunit 依赖注入的文章,今天这篇文章将结合我在 .NET Conf 上的分享,更加系统的分享一下在测试中的应用案例。

之所以想分享这个话题是因为我觉得在我们开发过程中测试是非常重要的一部分,高质量项目的一个重要指标就是测试覆盖率,同时依赖注入已经是一个现代化应用中不可缺少的一部分,我们的 .NET Core 也是从一开始就集成了依赖注入,依赖注入对于测试项目也是不能缺席的。

xunit 是 .net 里目前使用的最多的测试组件,Xunit.DependencyInjection 是大师写的一个 xunit 依赖注入的扩展,它是基于微软的 GenericHost(通用主机) 来实现的,使用它我们可以很轻松的实现依赖注入,很好的和 .NET Core 做集成。

How it works

那它是如何工作的呢?我们一起来看一下它的执行流程,它的执行流程分为四步

首先需要构建一个 Host,然后启动这个 Host,启动完成后执行测试用例,最后终止这个 Host

执行流程

Host 又是如何构建的呢?我们一起看一下,Host 的构建也是分为四步

第一步,创建一个 HostBuilder,大多数情况下我们不需要用这个方法,使用默认的实现就好

第二步,Host 配置,对 Host 做一些自定义配置

第三步,服务配置,注册需要的服务

第四步,Configure,可以做一些初始化的配置,比如配置初始化以及测试数据的初始化等

Host构建流程

我们可以在测试项目里创建一个 Startup 类来控制 Host 的构建过程

示例

接着我们来看一些实际的测试示例,示例分为三部分,首先是一些基本用法,然后是和其他组件的集成,最后是一些扩展用法

Get Started

首先来看一下 Startup 的用法,这个 Startup 和 asp.net core 里的 Startup 是很像的,无论是使用方式上还是实现上都是类似的,有兴趣的可以看一下源码对比一下,我们来看一下使用方式,通过下面的示例来感受一下

如果你只需要注册服务,直接在 Startup 中添加一个 ConfigureServices 方法,在这个方法中注册自己需要的服务即可,和 asp.net core 并无太多不同

如果你需要做一些初始化的工作,可以加一个 Configure 方法,在这个方法中实现自己的初始化逻辑就可以了,如果初始化的时候需要获取注入的服务实例,直接作为方法参数就可以,类似于 asp.net core 中 Configure 方法,只是不需要配置 Http 请求管道

如果你需要使用的配置,需要使用 Configuration,可以在 ConfigureHost 方法中通过 ConfigureHostConfiguration 扩展方法注册自己的配置

如果需要在注册服务的时候用到配置,可以在 ConfigureServices 方法中添加一个 HostBuildContext 的参数,HostBuilderContext 中的 Configuration 对象就是在 ConfigureHost 中注册的配置

如果需要在 Configure 方法中使用配置,直接添加一个 IConfiguration 的方法参数就可以了

我们再来看一下,如何在测试用例中使用注入的服务,一般情况下我们会直接通过构造器注入,在构造方法中添加需要注入的服务即可,除此之外我们还可以通过方法参数注入,结合 InlineDataMemeberData 使用,来看一下这个示例

IoC/AOP Integration

接着我们来看一下和其他组件的集成,AutoFac 是一个很流行的 IOC 组件,AspectCore 是柠檬大佬写的一个 AOP 框架,我们以这两个为例子来看一下如何集成第三方的依赖注入和 AOP 组件,前面我们已经提到它是基于微软的 GenericHost 实现的,而 asp.net core 从 3.0 开始也是基于 GenericHost 实现的,所以在 asp.net core 里怎么集成,在这里也是一样的,来看一下示例,只需要使用对应的 ServiceProviderFactory 就可以了,是不是很简单呢

Test Server Integration

然后我们来看一下如何和 TestServer 做集成,TestServer 主要用于集成测试,使用 TestServer 的好处在于它是基于内存进行交互的没有真正的 HTTP 请求和 TCP 链接,会非常的高效,而且也不会监听某一个端口,所以不会有端口权限的问题。

TestServer 的使用主要有两步,首先是服务的注册,可以使用 IHostBuilderIWebHostBuilder 的  UseTestServer 扩展方法注册 TestServer,可以使用 IHostGetTestClient 扩展方法来注册和 TestServer 进行交互的 HttpClient

服务注册好之后就可以在测试用例里通过注入的 HttpClient 请求 API 或页面了,可以参考这个例子

Extensions

Hosted Service

然后我们来看一些扩展用法,IHostedService 可以用来实现一些初始化的操作或者后台服务,我们可以使用 IHostedService 来实现对应用的 Ready 检查,应用 Ready 之后再开始执行测试用例,这在有些场景下是很有用的

我们在 k8s 中部署的应用一般都会有一个 HealthCheck/ReadinessCheck 的接口来供 k8s 的 liveness/readiness 探针来探测应用的状态,只有应用 Ready 之后才会对外部提供服务

这个示例就是一个使用 IHostedService 来实现等待应用 Ready 后再开始执行测试用例的一个 demo

注意:这里的等待不能在 StartupConfigure 方法中执行,因为 Configure 的执行是在调用 Host 的 StartAsync 方法之前执行的,而此时 webServer 还没有启动,所以是不能获取到 TestClient 的,而我们通过 HostedService 就可以在 Web Server 启动之后再执行我们的等待 Ready 逻辑

ITestOutputHelperAccessor

在测试中如果想要输出一个日志的话只能借助于 ITestOutputHelper 来输出,直接使用 Console.Write[Line] 是看不到任何输出的,ITestOutputHelper 只能在测试用例中使用,在测试服务中是不能使用的,Xunit.DependencyInjection 提供了一个 ITestOutputHelperAccessor 的服务,类似于 IHttpContextAccessor,我们可以借助它来在自定义的服务中获取 ITestOutputHelper 来输出日志

这里是一个简单的示例

Logging

再来看一个 OutputHelperAccessor 的实际应用,Xunit.DependencyInjection 提供了一个 Logging  的扩展,使得我们可以把测试过程中的日志输出出来,更好的帮助我们调试

集成方式也比较简单,可以参考这个示例,引用 Xunit.DependencyInjection.Logging 之后,在 LoggerFactory 中注册 XunitTestOutputLoggerProvider 即可

可以看到我们的日志直接输出出来了,默认的日志级别是 Information ,所以 Debug 级别的日志没有输出出来,有需要的话可以在注册的时候提供一个委托来控制是否要输出日志

Project Template

为了方便大家使用,我们提供了一个项目模板,可以通过一个命令就可以直接创建好一个测试项目,会包含一个默认的 Startup 不再需要自己去写方法了,使用的时候只需要根据需要做删减就可以了

默认的 TargetFramework 使用的是 netcoreapp3.1,可以通过 -f/--franework 指定自己想要使用的目标框架,比如说想要生成 net 5.0 的项目只需要指定 -f net5.0 就可以了

生成的内容如下所示:

More

最后列出来了一些可能会有帮助的链接,第一个是项目的源代码,第二个是 PPT 中所有示例的源代码,后面的是使用到的 Nuget 包。

这个 xunit 扩展的代码实现是非常值得学习的,有很多和 asp.net core 的实现是很像的,有需要的可以去看看源码学习一下。

希望我的分享对大家有所帮助,大家在使用过程中有遇到任何问题都可以随时联系我或者直接在 Github 上建 issue。

Reference

  • https://github.com/pengweiqhca/Xunit.DependencyInjection

  • https://github.com/WeihanLi/XunitDependencyInjection.Samples

  • https://www.nuget.org/packages/Xunit.DependencyInjection

  • https://www.nuget.org/packages/Microsoft.AspNetCore.TestHost

  • https://www.nuget.org/packages/Xunit.DependencyInjection.Logging

  • https://www.nuget.org/packages/Xunit.DependencyInjection.Template

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 端口qos,linux的qos机制 - cgroup篇 (2)

这篇重点讲述cgroup如何控制blkio子系统的qos,首先看下设置blkio.weight blkio.weight_device我的理解是blkio.weight是整个io子系统的权重值,而blkio.weight_device是针对特定的major:minor 设备的权重blkio.throttle.read_bps_device blkio.throttle.w…

利用 C# 中的 FileSystemWatcher 制作一个文件夹监控小工具

利用 C# 中的 FileSystemWatcher 制作一个文件夹监控小工具独立观察员 2020 年 12 月 26 日前一段看到微信公众号 “码农读书” 上发了一篇文章《如何使用 C# 中的 FileSystemWatcher》(翻译自:https://www.infoworld.com/article/3185447/how-to-work-w…

u盘安全删除 linux,为什么要安全删除U盘

原标题:为什么要安全删除U盘移除闪存设备时会对电脑造成危害吗?我们为什么要安全的移除它们?历史上,操作系统将磁盘作为信任对象不需要突然改变状态。当读写文件时,操作系统不希望文件在读写的过程中突然消失。如果文件…

如何在 C# 中使用 投影(Projection)

投影(Projection) 是一种可以将查询结果进行 塑性 的一种操作,你可以使用 投影 将一个 object 转成仅包含你需要属性的新对象,这篇文章中,我们就一起看看如何使用 投影 功能。C# 中的投影 LINQ 集成查询中有两个支持投影的扩展方法&#xff0…

Linux vi 双屏显示,manjaro AwesomeWM 上使用双显示器

安装manjaro时使用独显的单显示器,在主板上接第二个显示器一直没反应。几个问题和解决BIOS里检查是否关闭了集显开关大多数显卡的默认设置都会在识别独显后关闭集显,要使用集显上的接口需要单独设置。如果接口允许,最好将两个显示器都接在独显…

asp.net core中使用cookie身份验证

背景ASP.NET Core Identity 是一个完整的全功能身份验证提供程序,用于创建和维护登录名。 但是, cookie 不能使用基于的身份验证提供程序 ASP.NET Core Identity 。配置在 Startup.ConfigureServices 方法中,创建具有 AddAuthentication 和 A…

Linux语言写的高通滤波,高通滤波器c语言实现

描述高通滤波器,又称低截止滤波器、低阻滤波器,允许高于某一截频的频率通过,而大大衰减较低频率的一种滤波器。它去掉了信号中不必要的低频成分或者说去掉了低频干扰。高通滤波器是一种让某一频率以上的信号分量通过,而对该频率以…

在 WSL Ubuntu 上使用 .NET 进行跨平台开发新手入门

翻译自 haydenb 2020年6月3日的文章《Getting started with cross-platform development using .NET on Ubuntu on WSL》 [1].NET 是一个开源软件框架,用于在 Linux、Windows 和 macOS 上构建跨平台应用程序。WSL 上的 Ubuntu [2]允许您同时为 Ubuntu 和 Windows 构…

linux 全双工 wifi热点,Linux中的同时套接字读/写(“全双工”)(特别是aio)

我正在移植构建在ACE Proactor框架之上的应用程序.该应用程序适用于VxWorks和Windows,但在使用librt的内核2.6.X.X的Linux(CentOS 5.5,WindRiver Linux 1.4和3.0)上无法运行.我把问题缩小到一个非常基本的问题:应用程序在套接字上开始异步(通过aio_read)读取操作,然…

明源云·天际,地产⾏业的Salesforce Lightning Platform

源宝导读:2020年11月6日,明源云在CIO峰会上正式对外发布了“天际开放平台”,这是明源云凝聚其20多年行业经验打造的一款企业级PaaS平台。本文将介绍我们对企业级PaaS平台的行业思考,以及为加速泛地产生态链数字化转型而做的技术创…

c程序设计语言选修难吗,欢迎大家选修C语言程序设计这门课,本帖解释一下一些常见的问题...

置顶欢迎大家选修C语言程序设计这门课,本帖解释一下一些常见的问题叶卡林娜发表于2017年01月05日首先欢迎大家选修浙大翁恺老师的C语言程序设计课程。开课2天就看到讨论区已经有这么多帖子,说明同学们的学习热情很高。结合前几次开课的经验以及目前在讨论…

IdentityServer4系列 | 支持数据持久化

一、前言在前面的篇章介绍中,一些基础配置如API资源、客户端资源等数据以及使用过程中发放的令牌等操作数据,我们都是通过将操作数据和配置数据存储在内存中进行实现的,而在实际开发生产中,我们需要考虑如何处理数据持久化呢&…

c语言修仙受控可看吗,强推三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花...

大家好,我是小龙。今天我给大家推荐三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花!一《c语言修仙》【一十四洲】【简介】: 林浔是一个程序员,通宵编代码后发现自己身体内多了一个程序输入窗口。他尝试编了一个循环程序…

【Vue】Vue与ASP.NET Core WebAPI的集成

SPA单页面应用已经遍地开花,熟知的三大框架,Angular、Vue和React,其中Angular与React均可集成至ASP.NET Core,且提供了相关了中间件。但是Vue没有:“As far as I’m aware, we don’t have plans to introduce Vue-specific featu…

引入Jaeger——封装

随着微服务的普及,微服务间的调用全链路跟踪也火了起来,Jaeger(https://www.jaegertracing.io/)是CNCF孵化的全链路跟踪型项目,在.net core中,提供了一个Jaeger的Nuget(https://github.com/jaegertracing/jaeger-client-csharp)包…

c语言歌手预测成绩,5个裁判可以对10个歌手进行打分,计算各个歌手的最终得分排列...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼if(flag0){printf("\n歌手信息为空,请利用键盘输入或文件读入!\n\n");printf("按任意键返回......");getchar(); getchar();}fpfopen("c:\\backup1.txt","w");for(…

BeetleX自定义http/websocket压测用例视频

虽然BeetleX扩展了tcp/websocket/webapi压测工具(工具下载可以访问https://github.com/beetlex-io/TCPBenchmarks),但测试工具都是针对消息定义来进行测试,很难整合完整的业务流程;如果能写代码那BeetleX组件提供一个测试组件可以更好地完成针…

临近年关,发生两起磁盘占满引发的服务下线故障

一口气说两个因为磁盘空间不足引发的应用故障。作为拿起键盘一把梭的Coder, 开发--->部署-->收工--->心旷神怡,滋一口82年的可乐.过了几个月,服务突然下线了!CTO又有杀程序员祭天的理由了!事故1:Azure App Se…

c语言幼儿园积木游戏,幼儿园《积木游戏》课件【三篇】

【导语】课件制作本身就是作者综合素养的一种体现,它显现出制作者对教育、教学、教材改革方向的把握,对课堂教学的理解,对现代教育技术的领悟。因此教师在设计课件时一定要吃透教学内容,设计出符合教学的方案用于课件。下面是无忧…

c语言 listview,C语言 SDK编程之通用控件的使用--ListView

一、ListView控件属于通用控件CONTROL中的一种,在SDK编程方式时要使用通用控件必须包含comctl32.dll,所以代码中要有头文件: commctrl.h 导入库:comctl32.lib在使用通用控件之前应该先调用InitCommonControls();初始化它以ListView控件为例…