(29/30)みんなで学ぶBlazor:Blazor単体テスト

(29/30)みんなで学ぶBlazor:Blazor単体テスト

システム開発において最も退屈なプロセスは、おそらくバグ修正です。特に、null オブジェクトにアクセスしようとするエラー(`Object reference not set to an instance of an object.`)は、多くの初心者が最初に直面する問題です。退屈なバグ修正から解放されるために、この記事では「単体テスト」を紹介します。

最終更新 2021/12/25 20:39
StrayaWorker
読了目安 2 分
カテゴリ
Blazor
テーマ
みんなで学ぶBlazorシリーズ
タグ
.NET C# ASP.NET Core Blazor

システム開発の中で最も退屈なプロセスといえば、バグ修正です。特に、nullオブジェクトに対して値を取得しようとするエラー(Object reference not set to an instance of an object.)は、プログラミングを始めたばかりのほとんどの人が最初に直面する問題でしょう。この退屈なバグ修正から解放されるために、この記事ではユニットテストを紹介します。

Blazorのユニットテストは一般的なC#プログラミングとは少し異なり、主にComponentのページ表示ロジックの確認期待されるHTMLタグと実際のページに差異がないかをチェックします。なぜなら、Blazorはサーバーサイド言語で記述されてレンダリングされるフロントエンドフレームワークだからです。データに誤りがないかを検証する場合は、通常のC#のユニットテストになります。

現在、MicrosoftのテストフレームワークにはMSTestNUnitxUnitの3種類がありますが、どれもBlazorに対応していません。幸いなことに、コミュニティの愛好家がbUnitプロジェクトを作成し、テストを容易にしてくれました。ただし、bUnitはフレームワークではなくプロジェクトなので、まず3つのテストフレームワークのいずれかのプロジェクトを作成してから、NuGetbUnitをダウンロードする必要があります。

まず、ソリューションの下にテストプロジェクトBlazorServerMsTestを作成します。ここでは筆者はMSTestフレームワークを使用します。作成後、プロジェクト名をダブルクリックしてcsprojファイルを開き、Sdkが"Microsoft.NET.Sdk"になっていることを確認します。これを"Microsoft.NET.Sdk.Razor"に変更しないと、BlazorコンパイラRazor Componentをレンダリングしません。TargetFrameworknet6.0に変更する必要があります。これにより、私たちのBlazorServerプロジェクトと互換性が取れます。

次に、NuGetからbunitをダウンロードし、メインプロジェクトBlazorServerを参照します。テストするComponentがデータを使用しないのであれば、これで準備は完了です。しかし、現実的にはほとんどの場合、データとのやり取り、つまりServiceが必要です。そのため、ダミーデータを生成する``Serviceをダウンロードする必要があります。筆者はNSubstituteを使用しています。

(注: テストメソッドをすべてrazorファイルの@code ブロックに記述したい場合は、_Import.razorに使用するnamespaceを配置する必要があります。しかし、筆者はcode behind方式を使用しているため、配置しません。)

ユニットテストは3つの部分で構成されます。ArrangeActAssertです。Arrangeテスト前の準備Actテスト対象の検出Assertテスト結果です。

最初のdiv.cardのHTML結果をテストしてみましょう。まずWebページを開き、最初のcard classを持つ部分をコピーします。ここでのUser Idはデータに応じて変化します。

下図の19行目でbUnitのテストエンティティを作成し、ctxに代入しています。20行目ではNSubstituteを使用してダミーのIUserRepositoryを作成しています。21~23行目ではGetUsersAsync()を呼び出していますが、ダミーのList()を渡しており、その中には1組のCustomUserViewModelだけが含まれています。ここでは意図的に間違ったデータを与えています。24行目ではDIを使用してIUserRepositoryサービスを登録しています。

27行目でbUnitを使ってUserManagementをレンダリングし、cut(component under test)に代入しています。しかし、UserManagement全体を比較するには多くのHTMLタグを貼り付ける必要があるため、Find()を使用して最初のcard classを持つタグを探します。Find()ではCSSセレクターを使用するため、タグ、class、idなどを指定できます。

31行目以降では、見つけた要素とMarkupMatches()に配置したHTMLタグを比較しています。筆者は複数行を使用していますが、スペースを取りたくない場合はすべて1行にまとめても構いません。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:ポリシーベースの認可

以前に「ASP.NET Core Identity」は「Claim」ベースの検証を使用すると述べましたが、実は「ASP.NET Core Identity」には異なる種類の認可方法があります。最も簡単な「ログイン認可」「ロール認可」「Claim認可」ですが、これらはすべて同じ方法で実現されています:原則認可(ポリシーベースの認可)です。

続きを読む