(29/30)大家一起學Blazor:Blazor單元測試

(29/30)大家一起學Blazor:Blazor單元測試

開發一個系統最無聊的過程大概就是解決 Bug 了,尤其是那種嘗試對 null 物件取值的錯誤(`Object reference not set to an instance of an object.`),這應該是大部分人剛踏入程式設計領域最常碰到的問題,為了從枯燥的解決 Bug 過程解脫,這篇就來介紹`單元測試`。

最後更新 2021/12/25 下午8:39
StrayaWorker
預計閱讀 4 分鐘
分類
Blazor
專題
一起學Blazor系列
標籤
.NET C# ASP.NET Core Blazor

開發一個系統最無聊的過程大概就是解決 BUG 了,尤其是那種嘗試對 null 物件取值的錯誤(Object reference not set to an instance of an object.),這應該是大部分人剛踏入程式設計領域最常碰到的問題。為了從枯燥的解決 BUG 過程中解脫,這篇就來介紹「單元測試」。

「Blazor 的單元測試」跟一般 C# 程式設計不太一樣,主要是「檢查 Component 的頁面呈現邏輯」、「預期產生的 HTML 標籤跟實際頁面有無差異」,畢竟 Blazor 是以後端語言編寫而渲染的前端框架,如果要驗證資料有無錯誤,就是一般 C# 的單元測試了。

目前微軟的測試框架有 MSTestNUnitxUnit 三種,「但都不包含 Blazor」,還好有社群愛好者建立了 bUnit 專案方便測試,不過 bUnit 並非框架而是專案,所以必須先建立三種測試框架之一的專案,再去 NuGet 下載 bUnit

首先在方案底下建立測試專案 BlazorServerMsTest,這邊筆者用 MSTest 框架。建立好後在專案名稱上點兩下開啟 csproj 檔案,會看到 Sdk 為 "Microsoft.NET.Sdk",要改成 "Microsoft.NET.Sdk.Razor",否則「Blazor 編譯器」不會渲染 Razor ComponentTargetFramework 則要改成 net6.0,這樣才能跟我們的 BlazorServer 專案相容。

接著去 NuGet 下載 bunit,並且引用主專案 BlazorServer。如果要測試的 Component 沒有用到資料,這樣就完成前期作業了。但現實情況都是需要跟資料互動,也就是需要 Service,所以要下載可以「產生假資料」的 Service,筆者用的是 NSubstitute

(**註:**如果想把測試方法都寫在 razor 檔案的 @code 區塊,就需要在 _Import.razor 放置用到的 namespace,但因為筆者都用 code behind 的方式就不放了。)

單元測試中分為三個部分:ArrangeActAssertArrange 是指「測試前的準備」,Act 是「找出要測試的項目」,Assert 則是「測試的結果」。

我們來測試第一個 div.card 的 HTML 結果,先打開網頁去複製第一個有 card class 的內容,這邊的 User Id 會隨資料改變。

下圖的第 19 行建立了 bUnit 這個測試實體並賦值給 ctx,第 20 行則利用 NSubstitute 建立假的 IUserRepository,第 21 到 23 行呼叫了 GetUsersAsync() 不過丟了一個「假的 List()」,裡面只有一組 CustomUserViewModel,這邊故意給錯誤的資料;第 24 行「利用 DI 註冊 IUserRepository 服務」。

第 27 行「利用 bUnit 渲染出 UserManagement」並賦值給 cut (component under test),但如果要比較整個 UserManagement 要貼上很多 HTML 標籤,所以再用 Find() 找出第一個有 card class 的標籤。Find() 用的是 CSS 選擇器,代表可以放入標籤、class 或是 id 等等。

第 31 行之後就是用找出來的 element 跟我們放進 MarkupMatches() 的 HTML 標籤做比較。筆者這邊用的是多行,如果不想佔版面的人也可以全部濃縮成一行,bUnit 不會比較斷行

接著就是要實際測試了,可以按 ctrl + r, a 或是從上方的測試頁籤找到 Test Explorer,然後就能看到測試失敗,會告訴你「實際的 HTML 跟預期的 HTML 差在哪裡」,因為我們給的假資料跟預期的不同,所以出錯了。

我們把假資料的 UserId 跟 UserName「改成跟預期的 HTML 資料一樣」,按下 ctrl r, t,就能看到通過測試了。

引用:

  1. Creating a new bUnit test project
  2. Writing tests for Blazor components
  3. Mocking with NSubstitute
繼續探索

延伸閱讀

更多文章
同分類 / 同標籤 2021/12/25

(28/30)大家一起學Blazor:Policy-based authorization

之前有說到`ASP.NET Core Identity` 使用的是基於`Claim` 的驗證,其實`ASP.NET Core Identity` 有不同類型的授權方式,最簡單的`登入授權`、`角色授權`、`Claim 授權`,但上述幾種都是以一種方式實現:原則授權(`Policy-based authorization`)。

繼續閱讀