統合テスト

テンプレートから生成されるすべてのプロジェクトには、配線されて実行可能な <YourProject>.Tests.Integration プロジェクトが含まれています。そのテストはモックではなく 実際のDataverse環境 に対して行われます。なぜなら、ポータルで壊れるほとんどの要素はモックが置き換える継ぎ目(クエリ翻訳、メタデータ、フォーマット、権限)に存在しているからです。ベースクラスは両側それぞれに2つずつ用意されています。

プロジェクトの内容

テンプレートはこれらのファイルを出荷します。リポジトリ内の通常のソースソースなので、自由に変更してください。

ファイル 目的
PortalEndpointTestBase.cs メモリでポータルを起動し、それに対して HttpClient を公開します。これを基にエンドポイントや権限テストを導き出します。
TestBase.cs 認証済みのDataverse接続を持つサービスコンテナを構築します。そこから自分のサービスやロジックを直接呼び出すために派生します。
TestAuthentication.cs テスト認証スキームと、リクエストが誰として実行されるかを決定する TestUserContext です。
appsettings.json, xunit.runner.json 非秘密設定や、コレクションをシリアルに保つxunitランナーの設定などです。
ExampleTests.cs, README.md 両方の基地の実例(実際の記録を指すまで飛ばし)、そして簡単なローカルな参照。

基地の選択

この二つは補完的で、異なる層を試し、健康的なスイートでは両方を活用します。

構成と秘密

D365:Url、テストがappsettings.jsonで実行されるべき環境、つまり開発環境や使い捨て環境を指し示します。テストはレコードを作成・削除します。認証情報はユーザーシークレットから来ており、テストプロジェクトは意図的にウェブプロジェクトと同じUserSecretsId宣言しているため、すでにローカルで動作しているポータルにはこれ以上の処理は不要です。明示的に設定するには:

ソースはユーザーシークレット appsettings.json →環境変数→レイヤー化されているため、ビルドエージェントは環境変数(D365__ClientSecret、ダブルアンダースコアを使用)を通じてファイルに触れずにすべてを提供できます。クライアントシークレットはコミットされている appsettings.jsonに入れてはいけません。

注記

テストを実行するのにライセンスキーは必要ありません。インメモリホストはループバックアドレスでリスニングしており、ループバックはループバックなしでライセンスされています — Portal Websiteのレコードもテストダブルも必要ありません。

エンドポイントと権限のテスト

PortalEndpointTestBaseから派生し、Clientでリクエストを行います。リクエストは匿名で開始されます。これはエンドポイントが匿名発信者を拒否する際の正しいデフォルトです。リダイレクトは実行されないため、テストは到達するページではなく302上で主張できます。

ユーザーとしての行動

SignInAs が手を伸ばすべきものです。認証情報のステップだけをスタブします。発行するプリンシパルは実際のサインインと同じ主張を含んでいるため、認可、権限ハンドラー、すべてのクレーム読み取り拡張は本番環境と同じように動作します。パスワードもプロビジョニングもなく、単一のテストでリクエスト間のアイデンティティを変更できます。

LoginAsync ログインエンドポイントに本物の認証情報を投稿し、サインインパス自体がテストされている時のためにクッキーを保持します。パスワードと確認済みのメールを持つ連絡先が必要なため、処理は遅くなります。両者は共存し、なりすましユーザーが設定されていない場合はベースが本物のクッキーに戻ります。

注記

LoginAsync ReactおよびBlazor WebAssembly/Autoホスト向けにマッピングされたJSON認証エンドポイントが必要です。サーバーレンダリングされたBlazorプロジェクトはフォーム投稿を通じてRazor Accountページにサインインするため、 /api/auth/login はそこにマッピングされず、 LoginAsync は404 — SignInAsを使い、すべてのホストで動作します。

セットアップ、解体および代替

通常のニーズを満たすフックは3つあります。 ConfigureTestServices はアプリケーション自身の登録後に動作するため、そこにある ReplaceProgram.cs に勝つことになります。これはアウトバウンド依存関係の偽物に立ち上がる方法です。 OnInitializedAsyncOnDisposingAsync は各テストをブラケットで区切り、シーディングとクリーンアップを行い、テストが失敗しても分解作業が行われます。

重要

これらのテストはポータルを起動させるため、起動を妨げるものはポータルも停止させます。特に、強化認可が有効の場合、ホストは起動時に設定済み のウェブサイトID を検証し、実際の powerpagesite IDが提供されるまでガイダンスで失敗します。これはポータルを起動する前提条件と同じです。

テストサービスとロジック

TestBaseから導き出し、テスト対象のコードが必要とするものを登録し、それを解決します。Dataverseクライアントはすでに認証されています。

ユーザーIDを CreateOrganizationService(userId) に渡してなりすましする — Dataverseはそのユーザー自身の権限を強制し、エンドポイントを介さずデータ側からレコードレベルのアクセスを確認する方法を教えます。

CreateWebApiHttpClientAsync() Dataverse Web API(/api/data/v9.2/)に対して認証されたクライアントを返し、SDKよりもODataで表現しやすい主張を返します。設定時にクライアントIDやシークレットのほか Azure:TenantId が必要です。

テストの進行方法

dotnet testで実行するか、IDEのテストエクスプローラーから実行してください。多くの特徴を書く前に知っておく価値のあるいくつかの特徴があります:

ベストプラクティス

スイートは本番環境ではなく、開発環境に向けてください。これらは実際のデータに対する書き込みであり、作成したものを削除するテストは、もしそれを一つに狙い定めれば実際のレコードも削除されます。