文章目錄
為 .NET Core Middleware 加上 Unit Test
.NET Core 的 Middleware 在 .NET Core 的 pipeline 中扮演了非常重要的角色,因此在實際應用上更需要確保功能與結果符合預期。第一次寫 middleware 的 unit test 順手紀錄過程,看看在 unit tese 上有沒有什麼需要留意的,
基本環境說明
- macOS Mojave 10.14.4
- .NET Core 2.2.101
- ASP.NET Core Web Application (MVC) 預設專案範本
- NuGet 套件
- FluentAssertions 5.6.0
- Microsoft.AspNetCore.Http 2.2.2
- nunit 3.11.0
- NUnit3TestAdapter 3.11.0
- Microsoft.NET.Test.Sdk 15.9.0
加入 Middleware (兩個方式擇一即可)
加上檢查 header : request 在未包含指定的 header (auth) 時,即丟出 InvalidOperationException
直接將在
Startup.cs
的Configure
方法中加入 middlewareapp.Use((context, next) => { var auth = context.Request.Headers["auth"]; if (!string.IsNullOrWhiteSpace(auth)) { return next(); } throw new InvalidOperationException("Missing header !!"); });C
為 middleware 建立獨立類別
AuthHeaderCheckMiddleware
加入 middleware
public class AuthHeaderCheckMiddleware { private readonly RequestDelegate _next; public AuthHeaderCheckMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var auth = context.Request.Headers["auth"]; if (!string.IsNullOrWhiteSpace(auth)) { await _next(context); } throw new InvalidOperationException("Missing header !!"); } }
註冊 middleware
註冊位置與上個方式相同,但需要留意想要在哪一層處理:愈早註冊就會愈早檢查,只是出現錯誤的可讀性就會愈差
app.UseMiddleware<AuthHeaderCheckMiddleware>();
撰寫 Middleware 的 Unit Test
建立 mock HttpContext
為了符合 Unit Test 的基本定義, mock HttpContext 的隔離動作不可少,.NET Core 在這點上有長足的進步,直接使用
DefaultHttpContext
即可,不需自行 fake (需要參考並 usingMicrosoft.AspNetCore.Http
)var httpContext = new DefaultHttpContext();
建立 Unit Test
未提供 auth header 時會出現 InvalidOperationException
[Test] public async Task AthHeaderCheckMiddleware_Without_header_Should_Get_InvalidOperatorException() { //arrange var target = new AuthHeaderCheckMiddleware((innerHttpContext) => null); var httpContext = new DefaultHttpContext(); var expect = new InvalidOperationException("Missing header !!"); //act Func<Task> action = () => target.InvokeAsync(httpContext); //assert action.Should().Throw<InvalidOperationException>() .WithMessage(expect.Message); }
提供 auth header 則出現 NullReferenceException (因 next 傳入 null)
[Test] public async Task AthHeaderCheckMiddleware_With_Auht_header_Should_Get_NullReferenceException() { //arrange var target = new AuthHeaderCheckMiddleware((innerHttpContext) => null); var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add("auth","test"); //act Func<Task> action = () => target.InvokeAsync(httpContext); //assert action.Should().Throw<NullReferenceException>(); }
心得
實際使用起來與過去 ASP.NET Web API 的 Message Handler 測試流程很像,但又更輕鬆點:不用建立 request object 也不用 mock HttpContex,使用體驗很棒,愈用 .NET Core 愈覺得好用呀
像這樣的中介層因為事關重大,沒有測試保護 (不管是 unit test 或是 integration test) 對於新加入團隊的成員難免都是進入障礙,團隊也很難確保穩定的產出品質,就算是團隊成員都很小心,開發時不會犯錯,也無法確保所有成員過了半年後還記得商業邏輯跟程式碼用意,雖然每個人立場不同(也許覺得測試很浪費時間),但也許該試著看看為什麼有那麼多人推崇測試
參考資訊
文章作者 Yowko Tsai
上次更新 2021-11-03
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。