在 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,一经查实,立即删除!

相关文章

利用 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语言写的高通滤波,高通滤波器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 构…

明源云·天际,地产⾏业的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)包…

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

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

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

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

蚂蚁调度AntJob-分布式任务调度系统

分布式任务调度系统,纯NET打造的重量级大数据实时计算平台,万亿级调度经验积累!面向中小企业大数据分析场景。开源地址:https://github.com/NewLifeX/AntJob使用教程:https://www.yuque.com/smartstone/blood/antjob体…

c语言怎么让图形界面单独显示,「分享」C语言如何编写图形界面

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼贴吧内经常有人问C语言是不是只能用于字符终端界面开发,不能用于图形界面。大家也都有回答,需要其他的库。MFC,GTK,QT。本人近期刚用GTK库加上纯C写成了第一个LINUX实用程序。现在与大…

如何在 ASP.NET Core 中 自定义中间件

ASP.NET Core 是一个跨平台,开源的,轻量级,高性能 并且高度模块化的web框架,同时扩展性也是非常强,你可以在 request -> response 请求管道中安插各种中间件来根据自己的场景定制化,比如说:监…

ASP.NET Core Authentication and Authorization

最近把一个Asp .net core 2.0的项目迁移到Asp .net core 3.1,项目启动的时候直接报错:InvalidOperationException: Endpoint CoreAuthorization.Controllers.HomeController.Index (CoreAuthorization) contains authorization metadata, but a middleware was not …

android dialog 自定义布局,如何设置AlertDialog的自定义布局?

调用我的对话框:alertDialog showInfoDialog(message "$wrongPasscodeMessage\n$retryMessage")方法如下:fun FragmentActivity.showInfoDialog(message: String?): AlertDialog? {return try {val customLayout layoutInflater.inflate(R.layout.custom_layout…

android 打开谷歌导航,国内开启google位置记录功能/android版google maps 7+上,恢复位置记录功能在国内使用(需root)...

android版google 地图在 7以后的版本上,位置记录功能在国内不能用了,提示本功能不能在中国使用。至少对本人,“位置记录”功能是非常有用的功能,尤其是骑车出行时记录自己的路线。目前还没找到替代产品。之前一段时间内恢复回旧版…

程序员过关斩将--少年派登录安全的奇幻遐想

“据说,这篇也是快餐,完全符合年轻人口味说到登录,无人不知无人不晓。每一个有用户体系的相关系统都会有登录的入口,登录是为了确认操作人的正确性。说到登录安全,其实是一个很伟大的命题,不过常用的手段也…