Während Sie Ihre App erstellen, möchten Sie möglicherweise den Zugriff auf Ihre Cloud Firestore-Datenbank sperren. Vor dem Start benötigen Sie jedoch differenziertere Cloud Firestore-Sicherheitsregeln. Mit dem Cloud Firestore-Emulator können Sie nicht nur Prototypen erstellen und die allgemeinen Funktionen und das Verhalten Ihrer App testen, sondern auch Komponententests schreiben, die das Verhalten Ihrer Cloud Firestore-Sicherheitsregeln überprüfen.
Schnellstart
Probieren Sie für einige grundlegende Testfälle mit einfachen Regeln das Schnellstartbeispiel aus.
Verstehen Sie die Sicherheitsregeln von Cloud Firestore
Implementieren Sie Firebase-Authentifizierung und Cloud Firestore-Sicherheitsregeln für serverlose Authentifizierung, Autorisierung und Datenvalidierung, wenn Sie die Mobil- und Web-Client-Bibliotheken verwenden.
Die Cloud Firestore-Sicherheitsregeln bestehen aus zwei Teilen:
- Eine
match
Anweisung, die Dokumente in Ihrer Datenbank identifiziert. - Ein
allow
, der den Zugriff auf diese Dokumente steuert.
Die Firebase-Authentifizierung überprüft die Anmeldeinformationen der Benutzer und bildet die Grundlage für benutzerbasierte und rollenbasierte Zugriffssysteme.
Jede Datenbankanforderung von einer mobilen/Web-Client-Bibliothek von Cloud Firestore wird anhand Ihrer Sicherheitsregeln bewertet, bevor Daten gelesen oder geschrieben werden. Wenn die Regeln den Zugriff auf einen der angegebenen Dokumentpfade verweigern, schlägt die gesamte Anfrage fehl.
Weitere Informationen zu Cloud Firestore-Sicherheitsregeln finden Sie unter Erste Schritte mit Cloud Firestore-Sicherheitsregeln .
Installieren Sie den Emulator
Um den Cloud Firestore-Emulator zu installieren, verwenden Sie die Firebase-CLI und führen Sie den folgenden Befehl aus:
firebase setup:emulators:firestore
Führen Sie den Emulator aus
Beginnen Sie mit der Initialisierung eines Firebase-Projekts in Ihrem Arbeitsverzeichnis. Dies ist ein häufiger erster Schritt bei der Verwendung der Firebase-CLI .
firebase init
Starten Sie den Emulator mit dem folgenden Befehl. Der Emulator läuft, bis Sie den Prozess abbrechen:
firebase emulators:start --only firestore
In vielen Fällen möchten Sie den Emulator starten, eine Testsuite ausführen und den Emulator dann herunterfahren, nachdem die Tests ausgeführt wurden. Sie können dies ganz einfach mit dem Befehl emulators:exec
tun:
firebase emulators:exec --only firestore "./my-test-script.sh"
Beim Start versucht der Emulator, auf einem Standardport (8080) zu laufen. Sie können den Emulator-Port ändern, indem Sie den Abschnitt "emulators"
Ihrer firebase.json
Datei ändern:
{ // ... "emulators": { "firestore": { "port": "YOUR_PORT" } } }
Bevor Sie den Emulator ausführen
Beachten Sie Folgendes, bevor Sie den Emulator verwenden:
- Der Emulator lädt zunächst die im Feld
firestore.rules
Ihrer Dateifirebase.json
angegebenen Regeln. Es erwartet den Namen einer lokalen Datei, die Ihre Cloud Firestore-Sicherheitsregeln enthält, und wendet diese Regeln auf alle Projekte an. Wenn Sie den lokalen Dateipfad nicht angeben oder die MethodeloadFirestoreRules
nicht wie unten beschrieben verwenden, behandelt der Emulator alle Projekte so, als hätten sie offene Regeln. - Während die meisten Firebase-SDKs direkt mit den Emulatoren arbeiten, unterstützt nur die
@firebase/rules-unit-testing
Bibliothek die Mock-auth
in Sicherheitsregeln, was Unit-Tests erheblich vereinfacht. Darüber hinaus unterstützt die Bibliothek einige emulatorspezifische Funktionen wie das Löschen aller Daten, wie unten aufgeführt. - Die Emulatoren akzeptieren auch über Client-SDKs bereitgestellte Firebase-Auth-Token für die Produktion und werten die Regeln entsprechend aus, sodass Sie Ihre Anwendung bei Integrations- und manuellen Tests direkt mit den Emulatoren verbinden können.
Führen Sie lokale Unit-Tests durch
Führen Sie lokale Unit-Tests mit dem v9 JavaScript SDK aus
Firebase vertreibt eine Unit-Testing-Bibliothek für Sicherheitsregeln sowohl mit seinem JavaScript-SDK der Version 9 als auch mit seinem SDK der Version 8. Die Bibliotheks-APIs unterscheiden sich erheblich. Wir empfehlen die v9-Testbibliothek, die schlanker ist und weniger Setup für die Verbindung mit Emulatoren erfordert und so eine versehentliche Nutzung von Produktionsressourcen sicher vermeidet. Aus Gründen der Abwärtskompatibilität stellen wir weiterhin die v8-Testbibliothek zur Verfügung .
- Allgemeine Testmethoden und Dienstprogrammfunktionen im v9 SDK
- Emulatorspezifische Testmethoden im v9 SDK
Verwenden Sie das Modul @firebase/rules-unit-testing
um mit dem Emulator zu interagieren, der lokal ausgeführt wird. Wenn Zeitüberschreitungen oder ECONNREFUSED
Fehler auftreten, überprüfen Sie noch einmal, ob der Emulator tatsächlich ausgeführt wird.
Wir empfehlen dringend, eine aktuelle Version von Node.js zu verwenden, damit Sie async/await
Notation verwenden können. Fast das gesamte Verhalten, das Sie testen möchten, betrifft asynchrone Funktionen, und das Testmodul ist für die Arbeit mit Promise-basiertem Code konzipiert.
Die v9 Rules Unit Testing-Bibliothek kennt die Emulatoren immer und berührt niemals Ihre Produktionsressourcen.
Sie importieren die Bibliothek mit v9 modularen Importanweisungen. Zum Beispiel:
import {
assertFails,
assertSucceeds,
initializeTestEnvironment
} from "@firebase/rules-unit-testing"
// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.
Nach dem Import umfasst die Implementierung von Unit-Tests Folgendes:
- Erstellen und Konfigurieren einer
RulesTestEnvironment
mit einem Aufruf voninitializeTestEnvironment
. - Einrichten von Testdaten ohne Auslösen von Regeln mithilfe einer praktischen Methode, mit der Sie diese vorübergehend umgehen können:
RulesTestEnvironment.withSecurityRulesDisabled
. - Einrichten von Testsuite- und Test-Vorher/Nachher-Hooks mit Aufrufen zum Bereinigen von Testdaten und -umgebung, wie
RulesTestEnvironment.cleanup()
oderRulesTestEnvironment.clearFirestore()
. - Implementieren von Testfällen, die Authentifizierungszustände nachahmen, mithilfe von
RulesTestEnvironment.authenticatedContext
undRulesTestEnvironment.unauthenticatedContext
.
Gängige Methoden und Hilfsfunktionen
Siehe auch emulatorspezifische Testmethoden im v9 SDK .
initializeTestEnvironment() => RulesTestEnvironment
Diese Funktion initialisiert eine Testumgebung für Regeleinheitentests. Rufen Sie diese Funktion zuerst für den Testaufbau auf. Für eine erfolgreiche Ausführung müssen Emulatoren ausgeführt werden.
Die Funktion akzeptiert ein optionales Objekt, das eine TestEnvironmentConfig
definiert, die aus einer Projekt-ID und Emulatorkonfigurationseinstellungen bestehen kann.
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
Diese Methode erstellt einen RulesTestContext
, der sich wie ein authentifizierter Authentifizierungsbenutzer verhält. An Anfragen, die über den zurückgegebenen Kontext erstellt werden, ist ein Schein-Authentifizierungstoken angehängt. Übergeben Sie optional ein Objekt, das benutzerdefinierte Ansprüche oder Überschreibungen für Authentifizierungstoken-Nutzlasten definiert.
Verwenden Sie das zurückgegebene Testkontextobjekt in Ihren Tests, um auf alle konfigurierten Emulatorinstanzen zuzugreifen, einschließlich der mit initializeTestEnvironment
konfigurierten.
// Assuming a Firestore app and the Firestore emulator for this example import { setDoc } from "firebase/firestore"; const alice = testEnv.authenticatedContext("alice", { … }); // Use the Firestore instance associated with this context await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
RulesTestEnvironment.unauthenticatedContext() => RulesTestContext
Diese Methode erstellt einen RulesTestContext
, der sich wie ein Client verhält, der nicht über die Authentifizierung angemeldet ist. An Anfragen, die über den zurückgegebenen Kontext erstellt werden, sind keine Firebase-Auth-Tokens angehängt.
Verwenden Sie das zurückgegebene Testkontextobjekt in Ihren Tests, um auf alle konfigurierten Emulatorinstanzen zuzugreifen, einschließlich der mit initializeTestEnvironment
konfigurierten.
// Assuming a Cloud Storage app and the Storage emulator for this example import { getStorage, ref, deleteObject } from "firebase/storage"; const alice = testEnv.unauthenticatedContext(); // Use the Cloud Storage instance associated with this context const desertRef = ref(alice.storage(), 'images/desert.jpg'); await assertSucceeds(deleteObject(desertRef));
RulesTestEnvironment.withSecurityRulesDisabled()
Führen Sie eine Test-Setup-Funktion mit einem Kontext aus, der sich so verhält, als wären die Sicherheitsregeln deaktiviert.
Diese Methode verwendet eine Rückruffunktion, die den Kontext zur Umgehung von Sicherheitsregeln übernimmt und ein Versprechen zurückgibt. Der Kontext wird zerstört, sobald das Versprechen gelöst/ablehnt wird.
RulesTestEnvironment.cleanup()
Diese Methode zerstört alle in der Testumgebung erstellten RulesTestContexts
und bereinigt die zugrunde liegenden Ressourcen, sodass ein sauberer Exit möglich ist.
Diese Methode ändert in keiner Weise den Status von Emulatoren. Um Daten zwischen Tests zurückzusetzen, verwenden Sie die anwendungsemulatorspezifische Methode zum Löschen von Daten.
assertSucceeds(pr: Promise<any>)) => Promise<any>
Dies ist eine Dienstprogrammfunktion für Testfälle.
Die Funktion stellt sicher, dass das bereitgestellte Promise, das einen Emulatorvorgang umschließt, ohne Verstöße gegen Sicherheitsregeln aufgelöst wird.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
Dies ist eine Dienstprogrammfunktion für Testfälle.
Die Funktion stellt sicher, dass das bereitgestellte Promise, das einen Emulatorvorgang umschließt, mit einem Verstoß gegen die Sicherheitsregeln abgelehnt wird.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
Emulatorspezifische Methoden
Siehe auch allgemeine Testmethoden und Dienstprogrammfunktionen im v9 SDK .
RulesTestEnvironment.clearFirestore() => Promise<void>
Diese Methode löscht Daten in der Firestore-Datenbank, die zur für den Firestore-Emulator konfigurierten projectId
gehören.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
Diese Methode ruft eine Firestore-Instanz für diesen Testkontext ab. Die zurückgegebene Firebase JS-Client-SDK-Instanz kann mit den Client-SDK-APIs (v9 modular oder v9 kompatibel) verwendet werden.
Visualisieren Sie Regelauswertungen
Mit dem Cloud Firestore-Emulator können Sie Clientanfragen in der Emulator Suite-Benutzeroberfläche visualisieren, einschließlich der Auswertungsverfolgung für Firebase-Sicherheitsregeln.
Öffnen Sie die Registerkarte Firestore > Anfragen , um die detaillierte Bewertungssequenz für jede Anfrage anzuzeigen.
Testberichte erstellen
Nachdem Sie eine Reihe von Tests ausgeführt haben, können Sie auf Testabdeckungsberichte zugreifen, die zeigen, wie jede Ihrer Sicherheitsregeln bewertet wurde.
Um die Berichte zu erhalten, fragen Sie einen verfügbar gemachten Endpunkt auf dem Emulator ab, während dieser ausgeführt wird. Für eine browserfreundliche Version verwenden Sie die folgende URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
Dadurch werden Ihre Regeln in Ausdrücke und Unterausdrücke unterteilt, über die Sie mit der Maus fahren können, um weitere Informationen zu erhalten, einschließlich der Anzahl der Auswertungen und zurückgegebenen Werte. Für die JSON-Rohversion dieser Daten fügen Sie die folgende URL in Ihre Abfrage ein:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
Unterschiede zwischen Emulator und Produktion
- Sie müssen nicht explizit ein Cloud Firestore-Projekt erstellen. Der Emulator erstellt automatisch jede Instanz, auf die zugegriffen wird.
- Der Cloud Firestore-Emulator funktioniert nicht mit dem normalen Firebase-Authentifizierungsablauf. Stattdessen haben wir im Firebase Test SDK die Methode
initializeTestApp()
in der Bibliothekrules-unit-testing
bereitgestellt, die einauth
benötigt. Das mit dieser Methode erstellte Firebase-Handle verhält sich so, als ob es sich erfolgreich als die von Ihnen angegebene Entität authentifiziert hätte. Wenn Sienull
übergeben, verhält es sich wie ein nicht authentifizierter Benutzer (z. B. schlagenauth != null
Regeln fehl).
Beheben Sie bekannte Probleme
Wenn Sie den Cloud Firestore-Emulator verwenden, können die folgenden bekannten Probleme auftreten. Befolgen Sie die nachstehenden Anleitungen, um etwaiges unregelmäßiges Verhalten zu beheben. Diese Hinweise wurden unter Berücksichtigung der Unit-Testing-Bibliothek für Sicherheitsregeln geschrieben, die allgemeinen Ansätze gelten jedoch für jedes Firebase SDK.
Das Testverhalten ist inkonsistent
Wenn Ihre Tests gelegentlich bestanden und nicht bestanden werden, auch wenn an den Tests selbst keine Änderungen vorgenommen wurden, müssen Sie möglicherweise überprüfen, ob sie ordnungsgemäß sequenziert sind. Die meisten Interaktionen mit dem Emulator erfolgen asynchron. Überprüfen Sie daher noch einmal, ob der gesamte asynchrone Code ordnungsgemäß sequenziert ist. Sie können die Reihenfolge korrigieren, indem Sie Versprechen entweder verketten oder await
Notation großzügig verwenden.
Überprüfen Sie insbesondere die folgenden asynchronen Vorgänge:
- Festlegen von Sicherheitsregeln, beispielsweise mit
initializeTestEnvironment
. - Lesen und Schreiben von Daten, beispielsweise mit
db.collection("users").doc("alice").get()
. - Operative Behauptungen, einschließlich
assertSucceeds
undassertFails
.
Tests bestehen nur beim ersten Laden des Emulators
Der Emulator ist zustandsbehaftet. Es speichert alle darauf geschriebenen Daten im Speicher, sodass alle Daten verloren gehen, wenn der Emulator heruntergefahren wird. Wenn Sie mehrere Tests mit derselben Projekt-ID ausführen, kann jeder Test Daten erzeugen, die sich auf nachfolgende Tests auswirken können. Sie können dieses Verhalten mit einer der folgenden Methoden umgehen:
- Verwenden Sie für jeden Test eindeutige Projekt-IDs. Beachten Sie, dass Sie in diesem Fall
initializeTestEnvironment
als Teil jedes Tests aufrufen müssen. Regeln werden nur für die Standardprojekt-ID automatisch geladen. - Strukturieren Sie Ihre Tests neu, damit sie nicht mit zuvor geschriebenen Daten interagieren (verwenden Sie beispielsweise für jeden Test eine andere Sammlung).
- Löschen Sie alle während eines Tests geschriebenen Daten.
Der Testaufbau ist sehr kompliziert
Beim Einrichten Ihres Tests möchten Sie möglicherweise Daten auf eine Weise ändern, die Ihre Cloud Firestore-Sicherheitsregeln eigentlich nicht zulassen. Wenn Ihre Regeln die Testeinrichtung komplex machen, versuchen Sie, RulesTestEnvironment.withSecurityRulesDisabled
in Ihren Einrichtungsschritten zu verwenden, damit Lese- und Schreibvorgänge keine PERMISSION_DENIED
-Fehler auslösen.
Danach kann Ihr Test Vorgänge als authentifizierter oder nicht authentifizierter Benutzer mithilfe von RulesTestEnvironment.authenticatedContext
bzw. unauthenticatedContext
ausführen. Dadurch können Sie überprüfen, ob Ihre Cloud Firestore-Sicherheitsregeln verschiedene Fälle korrekt zulassen/ablehnen.