Durante la creazione dell'app, ti consigliamo di bloccare l'accesso al database Cloud Firestore. Tuttavia, prima del lancio, è necessario un approccio più approfonditoCloud Firestore Security Rules. Con l'emulatore Cloud Firestore, oltre a creare prototipi e a testare le funzionalità e il comportamento generali della tua app, puoi scrivere test di unità che controllano il comportamento del tuo Cloud Firestore Security Rules.
Guida rapida
Per alcuni casi di test di base con regole semplici, prova l'esempio di avvio rapido.
Informazioni su Cloud Firestore Security Rules
Implementa Firebase Authentication e Cloud Firestore Security Rules per l'autenticazione, l'autorizzazione e la convalida dei dati serverless quando utilizzi le librerie client web e per dispositivi mobili.
Cloud Firestore Security Rules include due elementi:
- Un'istruzione
match
che identifica i documenti nel database. - Un'espressione
allow
che controlla l'accesso a questi documenti.
Firebase Authentication verifica le credenziali degli utenti e fornisce le basi per i sistemi di accesso basati sugli utenti e sui ruoli.
Ogni richiesta al database da una Cloud Firestorelibreria client mobile/web viene valutata in base alle tue regole di sicurezza prima di leggere o scrivere dati. Se le regole negano l'accesso a uno dei percorsi dei documenti specificati, l'intera richiesta non va a buon fine.
Scopri di più su Cloud Firestore Security Rules in Iniziare a utilizzare Cloud Firestore Security Rules.
Installa l'emulatore
Per installare l'emulatore Cloud Firestore, utilizza l'interfaccia a riga di comando Firebase esegui il comando riportato di seguito:
firebase setup:emulators:firestore
Esegui l'emulatore
Inizia inizializzando un progetto Firebase nella tua directory di lavoro. Si tratta di un primo passaggio comune quando si utilizza l'interfaccia a riga di comando di Firebase.
firebase init
Avvia l'emulatore utilizzando il seguente comando. L'emulatore verrà eseguito fino a quando non interrompi il processo:
firebase emulators:start --only firestore
In molti casi, è consigliabile avviare l'emulatore, eseguire una suite di test e poi spegnerlo al termine dei test. Puoi farlo facilmente utilizzando il comando
emulators:exec
:
firebase emulators:exec --only firestore "./my-test-script.sh"
Una volta avviato, l'emulatore tenterà di funzionare su una porta predefinita (8080). Puoi cambiare la porta dell'emulatore modificando la sezione "emulators"
del file firebase.json
:
{ // ... "emulators": { "firestore": { "port": "YOUR_PORT" } } }
Prima di eseguire l'emulatore
Prima di iniziare a utilizzare l'emulatore, tieni presente quanto segue:
- L'emulatore caricherà inizialmente le regole specificate nel campo
firestore.rules
del filefirebase.json
. Aspetta il nome di un file locale contenente il tuo Cloud Firestore Security Rules e applica queste regole a tutti i progetti. Se non fornisci il percorso del file locale o utilizzi il metodoloadFirestoreRules
come descritto di seguito, l'emulatore considera tutti i progetti come con regole aperte. - Anche se
la maggior parte degli SDK Firebase
funziona direttamente con gli emulatori, solo la libreria
@firebase/rules-unit-testing
supporta la simulazione diauth
nelle regole di sicurezza, semplificando notevolmente i test di unità. Inoltre, la libreria supporta alcune funzionalità specifiche dell'emulatore, come l'eliminazione di tutti i dati, come elencato di seguito. - Gli emulatori accetteranno anche i token di produzione di Firebase Authentication forniti tramite gli SDK client e valuteranno le regole di conseguenza, il che consente di collegare la tua applicazione direttamente agli emulatori nei test di integrazione e manuali.
Esegui test locali delle unità
Eseguire test locali delle unità con l'SDK JavaScript 9
Firebase distribuisce una libreria di test di unità delle regole di sicurezza sia con l'SDK JavaScript di versione 9 sia con l'SDK di versione 8. Le API della libreria sono molto diverse. Consigliamo la libreria di test v9, che è più snella e richiede meno configurazione per connettersi agli emulatori e quindi evitare in modo sicuro l'uso accidentale delle risorse di produzione. Per la compatibilità con le versioni precedenti, continuiamo a mettere a disposizione la libreria di test v8.
- Metodi di test e funzioni di utilità comuni nell'SDK versione 9
- Metodi di test specifici per l'emulatore nell'SDK v9
Utilizza il modulo @firebase/rules-unit-testing
per interagire con l'emulatore eseguito localmente. Se si verificano timeout o errori ECONNREFUSED
, verifica che l'emulatore sia effettivamente in esecuzione.
Ti consigliamo vivamente di utilizzare una versione recente di Node.js per poter utilizzare la notazione async/await
. Quasi tutti i comportamenti che potresti voler testare richiedono funzioni asincrone e il modulo di test è progettato per funzionare con il codice basato su promesse.
La libreria di test delle unità delle regole 9 è sempre consapevole degli emulatori e non tocca mai le risorse di produzione.
Importa la libreria utilizzando le istruzioni di importazione modulari della versione 9. Ad esempio:
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.
Una volta importati, l'implementazione dei test di unità prevede:
- Creazione e configurazione di un
RulesTestEnvironment
con una chiamata ainitializeTestEnvironment
. - Configurazione dei dati di test senza attivare le regole, utilizzando un metodo di comodità che consente di ignorarle temporaneamente
RulesTestEnvironment.withSecurityRulesDisabled
. - Configurazione di suite di test e hook prima/dopo per test con chiamate per pulizia dell'ambiente e dei dati di test, ad esempio
RulesTestEnvironment.cleanup()
oRulesTestEnvironment.clearFirestore()
. - Implementazione di casi di test che simulano gli stati di autenticazione utilizzando
RulesTestEnvironment.authenticatedContext
eRulesTestEnvironment.unauthenticatedContext
.
Metodi e funzioni di utilità comuni
Consulta anche i metodi di test specifici dell'emulatore nell'SDK v9.
initializeTestEnvironment() => RulesTestEnvironment
Questa funzione inizializza un ambiente di test per i test delle unità delle regole. Chiama innanzitutto questa funzione per la configurazione del test. Per un'esecuzione corretta è necessario che gli emulatori siano in esecuzione.
La funzione accetta un oggetto facoltativo che definisce un TestEnvironmentConfig
,
che può essere costituito da un ID progetto e da impostazioni di configurazione dell'emulatore.
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
Questo metodo crea un RulesTestContext
, che si comporta come un utente autenticato di Authentication. Alle richieste create tramite il contesto restituito verrà allegato un token di autenticazione simulato. Se vuoi, puoi passare un oggetto che definisce rivendicazioni personalizzate o override per i payload dei token di autenticazione.
Utilizza l'oggetto contesto test restituito nei test per accedere a eventuali istanze di emulatore configurate, incluse quelle configurate con initializeTestEnvironment
.
// 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
Questo metodo crea un RulesTestContext
, che si comporta come un cliente che non ha eseguito l'accesso tramite l'autenticazione. Le richieste create tramite il contesto restituito non avranno token Firebase Auth allegati.
Utilizza l'oggetto contesto test restituito nei test per accedere a eventuali istanze di emulatore configurate, incluse quelle configurate con initializeTestEnvironment
.
// 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()
Esegui una funzione di configurazione del test con un contesto che si comporta come se le Regole di sicurezza fossero disabilitate.
Questo metodo accetta una funzione di callback, che accetta il contesto di aggiramento delle regole di sicurezza e restituisce una promessa. Il contesto verrà distrutto una volta che la promessa viene risolta / rifiutata.
RulesTestEnvironment.cleanup()
Questo metodo elimina tutti i RulesTestContexts
creati nell'ambiente di test e pulizia delle risorse sottostanti, consentendo un'uscita pulita.
Questo metodo non modifica in alcun modo lo stato degli emulatori. Per reimpostare i dati tra un test e l'altro, utilizza il metodo di cancellazione dei dati specifico dell'emulatore dell'applicazione.
assertSucceeds(pr: Promise<any>)) => Promise<any>
Questa è una funzione di utilità per i casi di test.
La funzione afferma che la Promise fornita che racchiude un'operazione dell'emulatore verrà risolta senza violazioni delle regole di sicurezza.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
Questa è una funzione di utilità per i casi di test.
La funzione afferma che la Promise fornita che racchiude un'operazione dell'emulatore verrà rifiutata con una violazione delle regole di sicurezza.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
Metodi specifici per l'emulatore
Consulta anche i metodi di test e le funzioni di utilità comuni nell'SDK v9.
RulesTestEnvironment.clearFirestore() => Promise<void>
Questo metodo cancella i dati nel database Firestore appartenenti al
projectId
configurato per l'emulatore Firestore.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
Questo metodo recupera un'istanza Firestore per questo contesto di test. L'istanza dell'SDK client Firebase JS restituita può essere utilizzata con le API SDK client (v9 modulare o v9 compatibile).
Visualizzare le valutazioni delle regole
L'emulatore Cloud Firestore ti consente di visualizzare le richieste del client nell'interfaccia utente di Emulator Suite, incluso il monitoraggio della valutazione per le regole di sicurezza di Firebase.
Apri la scheda Firestore > Richieste per visualizzare la sequenza di valutazione dettagliata per ogni richiesta.
Generare report di test
Dopo aver eseguito una suite di test, puoi accedere ai report sulla copertura dei test che mostrano in che modo è stata valutata ciascuna delle tue regole di sicurezza.
Per ottenere i report, esegui una query su un endpoint esposto sull'emulatore mentre è in esecuzione. Per una versione adatta ai browser, utilizza il seguente URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
In questo modo, le regole vengono suddivise in espressioni e sottoespressioni su cui puoi eseguire il passaggio del mouse per visualizzare ulteriori informazioni, tra cui il numero di valutazioni e i valori restituiti. Per la versione JSON non elaborata di questi dati, includi il seguente URL nella query:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
Differenze tra l'emulatore e la produzione
- Non è necessario creare esplicitamente un progetto Cloud Firestore. L'emulatore crea automaticamente qualsiasi istanza a cui viene eseguito l'accesso.
- L'emulatore Cloud Firestore non funziona con il normale flusso Firebase Authentication.
Nell'SDK Firebase Test, invece, abbiamo fornito il metodo
initializeTestApp()
nellarules-unit-testing
libreria, che accetta un campoauth
. L'handle Firebase creato con questo metodo si comporterà come se avesse eseguito l'autenticazione come qualsiasi entità fornita. Se passinull
, il valore si comporterà come un utente non autenticato (ad esempio, le regoleauth != null
non andranno a buon fine).
Risolvere i problemi noti
Durante l'utilizzo dell'emulatore Cloud Firestore, potresti riscontrare i seguenti problemi noti. Segui le indicazioni riportate di seguito per risolvere eventuali comportamenti irregolari riscontrati. Queste note sono scritte tenendo presente la libreria di test di unità delle Regole di sicurezza, ma gli approcci generali sono applicabili a qualsiasi SDK Firebase.
Il comportamento del test non è coerente
Se i test a volte passano e a volte non passano, anche senza modifiche ai test stessi, potrebbe essere necessario verificare che siano sequenziati correttamente.
La maggior parte delle interazioni con l'emulatore è asincrona, quindi verifica che tutto il codice asincrono sia sequenziato correttamente. Puoi correggere la sequenzialità concatenando le promesse o utilizzando liberamente la notazione await
.
In particolare, esamina le seguenti operazioni asincrone:
- Impostazione delle regole di sicurezza, ad esempio con
initializeTestEnvironment
. - Lettura e scrittura dei dati, ad esempio con
db.collection("users").doc("alice").get()
. - Affermazioni operative, tra cui
assertSucceeds
eassertFails
.
I test passano solo la prima volta che carichi l'emulatore
L'emulatore è stateful. Memorizza tutti i dati scritti in memoria, pertanto tutti i dati andranno persi ogni volta che l'emulatore si arresta. Se esegui più test sullo stesso ID progetto, ogni test può produrre dati che potrebbero influire sui test successivi. Per aggirare questo comportamento, puoi utilizzare uno dei seguenti metodi:
- Utilizza ID progetto univoci per ogni test. Tieni presente che, se scegli di farlo,
dovrai chiamare
initializeTestEnvironment
nell'ambito di ogni test; le regole vengono caricate automaticamente solo per l'ID progetto predefinito. - Ristruttura i test in modo che non interagiscano con i dati scritti in precedenza (ad esempio, utilizza una raccolta diversa per ogni test).
- Elimina tutti i dati scritti durante un test.
La configurazione del test è molto complicata
Quando configuri il test, potresti voler modificare i dati in un modo che Cloud Firestore Security Rules non consente. Se le regole rendono complessa la configurazione del test, prova a utilizzare RulesTestEnvironment.withSecurityRulesDisabled
nei passaggi di configurazione in modo che le letture e le scritture non attivino errori PERMISSION_DENIED
.
Dopodiché, il test può eseguire operazioni come utente autenticato o non autenticato utilizzando rispettivamente RulesTestEnvironment.authenticatedContext
e unauthenticatedContext
. In questo modo puoi verificare che Cloud Firestore Security Rules consenta / neghi correttamente diverse richieste.