Integrationstests

Jedes Projekt, das aus den Vorlagen generiert wird, enthält ein <YourProject>.Tests.Integration Projekt, das verkabelt und bereit zum Ausführen ist. Seine Tests basieren auf einer echten Dataverse-Umgebung statt auf Mocks, weil das meiste, was in einem Portal kaputtgeht, in den Nähten eines Mocks lebt – Abfrageübersetzung, Metadaten, Formatierung, Berechtigungen. Es werden zwei Basisklassen bereitgestellt, jeweils eine für jede Seite davon.

Was ist im Projekt enthalten

Die Vorlage liefert diese Dateien; sie sind normale Quellcodes in deinem Repository, also ändere sie frei.

Akte Zweck
PortalEndpointTestBase.cs Bootet dein Portal im Speicher und stellt ein HttpClient Signal gegen es frei. Daraus leide ich für Endpunkt- und Berechtigungstests ab.
TestBase.cs Erstellt einen Service-Container mit einer authentifizierten Dataverse-Verbindung. Leite daraus ab, um direkt deine eigenen Services und Logik aufzurufen.
TestAuthentication.cs Das Test-Authentifizierungsschema und das TestUserContext , das entscheidet, für wen eine Anfrage ausgeführt wird.
appsettings.json, xunit.runner.json Nicht-geheime Einstellungen und die Xunit-Runner-Konfiguration, die Sammlungen serielle hält.
ExampleTests.cs, README.md Es wurden Beispiele beider Basen ausgearbeitet (übersprungen, bis man sie auf echte Aufzeichnungen zeigt) und eine kurze lokale Referenz.

Die Wahl einer Basis

Die beiden ergänzen sich – sie testen verschiedene Schichten, und eine gesunde Suite nutzt beides.

Konfiguration und Geheimnisse

Zeigen D365:Url Sie auf die Umgebung, in der die Tests laufen appsettings.json sollten – eine Entwicklungs- oder Wegwerfumgebung, da Tests Datensätze erstellen und löschen. Zugangsdaten stammen aus Benutzergeheimnissen, und das Testprojekt deklariert absichtlich dasselbe UserSecretsId wie das Webprojekt, sodass ein Portal, das bereits lokal läuft, nichts Weiteres benötigt. Um sie explizit zu setzen:

Quellen sind → Benutzergeheimnissen → Umgebungsvariablen geschichtet appsettings.json , sodass ein Build-Agent alles über Umgebungsvariablen (D365__ClientSecret, unter Verwendung des doppelten Unterstrichs) liefern kann, ohne eine Datei zu berühren. Fügen Sie niemals das Client-Geheimnis in appsettings.json, das committed ist.

Anmerkung

Man braucht keinen Lizenzschlüssel, um Tests durchzuführen. Der In-Memory-Host hört über eine Loopback-Adresse, und Loopback ist ohne eine Lizenz lizenziert – kein Portal-Website-Datensatz und kein Test-Doppel erforderlich.

Test-Endpunkte und Berechtigungen

Man leitet ab und PortalEndpointTestBase stellt Anfragen mit Client. Anfragen beginnen anonym, was der richtige Standard ist, um zu behaupten, dass ein Endpunkt anonyme Anrufer abweist. Weiterleitungen werden nicht befolgt, sodass ein Test auf einer 302 statt auf der Seite ausgeführt werden kann, auf der er landen würde.

Handeln als Nutzer

SignInAs ist derjenige, zu dem man greifen muss. Er stubbt nur den Credential-Schritt – der von ihm ausgegebene Principal trägt dieselben Behauptungen, die auch eine echte Anmeldung ausgibt, sodass Autorisierung, die Berechtigungshandler und jede claim-reading-Erweiterung sich wie in der Produktion verhalten. Kein Passwort, keine Bereitstellung, und es kann die Identität zwischen Anfragen in einem einzigen Test ändern.

LoginAsync Speichert echte Zugangsdaten auf den Login-Endpunkt und behält den Cookie, wenn der Anmeldepfad selbst getestet wird. Er benötigt einen Kontakt mit Passwort und eine bestätigte E-Mail, daher ist er langsamer; beide existieren nebeneinander und die Basis greift auf das echte Cookie zurück, wenn kein Imitationsnutzer gesetzt wird.

Anmerkung

LoginAsync benötigt die JSON-Authentifizierungs-Endpunkte, die für die React- und Blazor-WebAssembly/Auto-Hosts zugeordnet sind. Ein servergerendertes Blazor-Projekt meldet sich über Formular an, postet stattdessen auf die Razor-Kontoseiten, ist daher /api/auth/login dort nicht zugeordnet und gibt 404 zurück – LoginAsync use SignInAs, was in jedem Host funktioniert.

Aufbau, Abbau und Auswechslungen

Drei Haken decken die üblichen Bedürfnisse ab.ConfigureTestServices Läuft nach den eigenen Registrierungen deiner Anwendung, also gewinnt Program.cs ein Replace Dort – der Weg, eine Fälschung für eine ausgehende Abhängigkeit einzusetzen. OnInitializedAsync Und OnDisposingAsync jeden Test für Seeding und Cleanup einzurahmen, und die Demontage läuft auch dann, wenn ein Test fehlschlägt.

Wichtig

Diese Tests starten dein Portal, also stoppt alles, was das Starten verhindert, auch sie. Insbesondere validiert der Host mit aktivierter verbesserter Autorisierung die konfigurierte Website-ID beim Start und scheitert mit Anleitung – bis eine echte powerpagesite ID bereitgestellt wird – dieselbe Voraussetzung wie das Ausführen des Portals.

Testdienste und Logik

Herleiten Sie aus TestBase, registrieren Sie, was der unter Test befindliche Code benötigt, und lösen Sie es auf. Der Dataverse-Client ist bereits authentifiziert.

Geben Sie eine Benutzer-ID weiter CreateOrganizationService(userId) , um sich auszugeben – Dataverse setzt dann die eigenen Rechte dieses Benutzers durch, was bedeutet, wie man den Zugriff auf Datenebene von der Datenseite überprüft und nicht über einen Endpunkt.

CreateWebApiHttpClientAsync() gibt einen Client zurück, der gegen die Dataverse Web API (/api/data/v9.2/) authentifiziert ist, für Assertions, die in OData leichter auszudrücken sind als über das SDK. Es benötigt Azure:TenantId in der Konfiguration sowie die Client-ID und das Geheimnis.

Wie die Tests ablaufen

Führe sie mit dotnet testoder aus dem Test-Explorer deiner IDE aus. Einige Eigenschaften sind zu kennen, bevor du viele schreibst:

Best Practice

Richte die Suite auf eine Entwicklungsumgebung, niemals auf die Produktion. Das sind echte Schreibvorgänge gegen echte Daten, und ein Test, der das Erstellte löscht, löscht den echten Datensatz, wenn du ihn auf einen zielst.