iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
自我挑戰組

ASP.NET Core & Blazor系列 第 29

Day29 Blazor 單元測試

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

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

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

首先在方案底下建立測試專案 BlazorServerMsTest,這邊筆者用 MSTest 框架,建立好後在專案名稱點兩下開啟csproj檔,會看到 Sdk 為 "Microsoft.NET.Sdk",要改成 "Microsoft.NET.Sdk.Razor",否則 Blazor 編譯器不會渲染 Razor Component,TargetFramework 則要改成netcoreapp5.0,這樣才能跟我們的 BlazorServer 專案相容。
https://ithelp.ithome.com.tw/upload/images/20210929/20140893T6uourEkRW.png
https://ithelp.ithome.com.tw/upload/images/20210929/20140893GL42f5XReN.png
https://ithelp.ithome.com.tw/upload/images/20210929/20140893Uk11nygSZq.png

接著去 NuGet 下載 bunit,並且參考主專案 BlazorServer,如果要測試的 Component 沒有用到資料,這樣就完成前置作業了,但現實狀況都是需要跟資料互動,也就是需要 Service,所以要下載可以產生假資料的 Service,筆者用的是 NSubstitute。
https://ithelp.ithome.com.tw/upload/images/20210929/20140893AlbqXm7p12.png
https://ithelp.ithome.com.tw/upload/images/20210929/20140893JRKbAK69kP.png

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

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

我們來測試第一個 div.card 的 HTML 結果,先開啟網頁去複製第一個有 card class,這邊的 User Id 會隨資料改變。
https://ithelp.ithome.com.tw/upload/images/20210929/201408934MxLnc0otM.png

下圖的19 行創建了 bUnit 這個測試實體並賦值給 ctx,20 行則利用 NSubstitute 建立的假的 IUserRepository,21 到 23 行呼叫了 GetUsersAsync() 不過丟了一個假的 List(),裡面只有一組 CustomUserViewModel,這邊故意給錯誤的資料,24 行利用 DI 註冊 IUserRepository 服務。
https://ithelp.ithome.com.tw/upload/images/20210929/20140893gv4r0hIxTp.png

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 差在哪裡,因為我們給的假資料跟預期的不同,所以出錯了。
https://ithelp.ithome.com.tw/upload/images/20210929/20140893yfctN7fAkL.png
https://ithelp.ithome.com.tw/upload/images/20210929/20140893yqnibfVvg8.png

我們把假資料的 UserIdUsreName 改成跟預期的 HTML 資料一樣,按下 ctrl r, t,就能看到通過測試了。
https://ithelp.ithome.com.tw/upload/images/20210929/20140893b1gY1R5WAZ.png
https://ithelp.ithome.com.tw/upload/images/20210929/20140893pWTZK8G3lN.png

Ref:Creating a new bUnit test project

Ref: Writing tests for Blazor components

Ref: Mocking with NSubstitute


上一篇
Day28 Policy-based authorization
下一篇
Day30 .NET 6 <ErrorBoundary>
系列文
ASP.NET Core & Blazor30

尚未有邦友留言

立即登入留言