在 xunit 測試項目中使用依賴注入

在 xunit 測試項目中使用依賴注入

Intro

以前寫過幾篇 xunit 依賴注入的文章,今天這篇文章將結合我在 .NET Conf 上的分享,更加系統的分享一下在測試中的應用案例。git

之因此想分享這個話題是由於我以爲在咱們開發過程當中測試是很是重要的一部分,高質量項目的一個重要指標就是測試覆蓋率,同時依賴注入已是一個現代化應用中不可缺乏的一部分,咱們的 .NET Core 也是從一開始就集成了依賴注入,依賴注入對於測試項目也是不能缺席的。github

xunit 是 .net 裏目前使用的最多的測試組件,Xunit.DependencyInjection 是大師寫的一個 xunit 依賴注入的擴展,它是基於微軟的 GenericHost(通用主機) 來實現的,使用它咱們能夠很輕鬆的實現依賴注入,很好的和 .NET Core 作集成。web

How it works

那它是如何工做的呢?咱們一塊兒來看一下它的執行流程,它的執行流程分爲四步app

首先須要構建一個 Host,而後啓動這個 Host,啓動完成後執行測試用例,最後終止這個 Host框架

執行流程

Host 又是如何構建的呢?咱們一塊兒看一下,Host 的構建也是分爲四步asp.net

第一步,建立一個 HostBuilder,大多數狀況下咱們不須要用這個方法,使用默認的實現就好ide

第二步,Host 配置,對 Host 作一些自定義配置學習

第三步,服務配置,註冊須要的服務測試

第四步,Configure,能夠作一些初始化的配置,好比配置初始化以及測試數據的初始化等ui

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 的使用主要有兩步,首先是服務的註冊,可使用 IHostBuilderIWebHostBuilderUseTestServer 擴展方法註冊 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

相關文章
相關標籤/搜索