Durante la creazione dell'app, potresti voler bloccare l'accesso al tuo Cloud Firestore database. Tuttavia, prima del lancio, avrai bisogno di regole di sicurezza di Cloud Firestore più sfumate Cloud Firestore Security Rules. Con l'emulatore Cloud Firestore, oltre a creare prototipi e testare le funzionalità e il comportamento generali dell'app, puoi scrivere test delle unità che controllano il comportamento di Cloud Firestore Security Rules.
Guida rapida
Per alcuni casi di test di base con regole semplici, prova l'esempio della guida rapida.
Informazioni su Cloud Firestore Security Rules
Implement Firebase Authentication and Cloud Firestore Security Rules per l'autenticazione, l'autorizzazione e la convalida dei dati senza server quando utilizzi le librerie client web e per dispositivi mobili.
Cloud Firestore Security Rules includono due elementi:
- Un'istruzione
matchche identifica i documenti nel database. - Un'espressione
allowche controlla l'accesso a questi documenti.
Firebase Authentication verifica le credenziali degli utenti e fornisce le basi per i sistemi di accesso basati su utenti e ruoli.
Ogni richiesta di database da una libreria client web/per dispositivi mobili Cloud Firestore viene valutata in base alle regole di sicurezza prima di leggere o scrivere dati. Se le regole negano l'accesso a uno qualsiasi dei percorsi dei documenti specificati, l'intera richiesta non va a buon fine.
Scopri di più su Cloud Firestore Security Rules in Inizia a utilizzare Cloud Firestore Security Rules.
Installare l'emulatore
Per installare l'emulatore Cloud Firestore, utilizza la CLI Firebase ed esegui il comando riportato di seguito:
firebase setup:emulators:firestore
Eseguire l'emulatore
Inizia inizializzando un progetto Firebase nella directory di lavoro. Questo è un primo passaggio comune quando si utilizza l'interfaccia a riga di comando di Firebase.
firebase init
Avvia l'emulatore utilizzando il comando seguente. L'emulatore verrà eseguito finché non interrompi il processo:
firebase emulators:start --only firestore
In molti casi, ti consigliamo di avviare l'emulatore, eseguire una suite di test e poi arrestarlo dopo l'esecuzione dei test. Puoi farlo facilmente utilizzando il comando emulators:exec:
firebase emulators:exec --only firestore "./my-test-script.sh"
Quando viene avviato, l'emulatore tenta di essere eseguito su una porta predefinita (8080). Puoi
modificare la porta dell'emulatore modificando la sezione "emulators" del tuo
firebase.json file:
{
// ...
"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.rulesdel filefirebase.json. Si aspetta il nome di un file locale contenente le tue Cloud Firestore Security Rules e applica quelle regole a tutti i progetti. Se non fornisci il percorso del file locale o utilizzi il metodoloadFirestoreRulescome descritto di seguito, l'emulatore considera tutti i progetti come se avessero regole aperte. - Sebbene
la maggior parte degli SDK Firebase
funzioni direttamente con gli emulatori, solo la libreria
@firebase/rules-unit-testingsupporta la simulazione diauthnelle regole di sicurezza, semplificando notevolmente i test delle unità. Inoltre, la libreria supporta alcune funzionalità specifiche dell'emulatore, come la cancellazione di tutti i dati, come indicato di seguito. - Gli emulatori accettano anche i token Firebase Authentication di produzione forniti tramite gli SDK client e valutano le regole di conseguenza, il che consente di collegare l'applicazione direttamente agli emulatori nei test di integrazione e manuali.
Eseguire test delle unità locali
Eseguire test delle unità locali con l'SDK JavaScript v9
Firebase distribuisce una libreria di test delle unità delle regole di sicurezza sia con l'SDK JavaScript versione 9 sia con l'SDK versione 8. Le API della libreria sono significativamente diverse. Ti consigliamo di utilizzare la libreria di test v9, che è più snella e richiede meno configurazione per la connessione agli emulatori, evitando così l'utilizzo accidentale delle risorse di produzione. Per la compatibilità con le versioni precedenti, continuiamo a rendere disponibile la libreria di test v8.
- Metodi di test e funzioni di utilità comuni nell'SDK v9
- Metodi di test specifici dell'emulatore nell'SDK v9
Utilizza il modulo @firebase/rules-unit-testing per interagire con l'emulatore in esecuzione in locale. Se ricevi errori di timeout o ECONNREFUSED, controlla 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 tutto il comportamento che potresti voler testare coinvolge funzioni asincrone e il modulo di test è progettato per funzionare con il codice basato su Promise.
La libreria di test delle unità delle regole v9 è sempre a conoscenza degli emulatori e non tocca mai le risorse di produzione.
Importa la libreria utilizzando le istruzioni di importazione modulare v9. 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, i test delle unità comportano:
- Creazione e configurazione di un
RulesTestEnvironmentcon una chiamata ainitializeTestEnvironment. - Configurazione dei dati di test senza attivare le regole, utilizzando un metodo pratico che consente di ignorarle temporaneamente,
RulesTestEnvironment.withSecurityRulesDisabled. - Configurazione della suite di test e dei hook before/after per test con chiamate per liberare spazio nei dati e nell'ambiente di test, come
RulesTestEnvironment.cleanup()oRulesTestEnvironment.clearFirestore(). - Implementazione di casi di test che simulano gli stati di autenticazione utilizzando
RulesTestEnvironment.authenticatedContexteRulesTestEnvironment.unauthenticatedContext.
Metodi e funzioni di utilità comuni
Vedi anche i metodi di test specifici dell'emulatore nell'SDK v9.
initializeTestEnvironment() => RulesTestEnvironment
Questa funzione inizializza un ambiente di test per il test delle unità delle regole. Chiama questa funzione per prima per la configurazione del test. Per l'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 dalle 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 di autenticazione autenticato. Le richieste create tramite il contesto restituito avranno un token di autenticazione simulato allegato. Facoltativamente, passa un oggetto che definisce rivendicazioni personalizzate o override per i payload dei token di autenticazione.
Utilizza l'oggetto del contesto di test restituito nei test per accedere a tutte le istanze dell'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().doc('/users/alice'), { ... });
RulesTestEnvironment.unauthenticatedContext() => RulesTestContext
Questo metodo crea un RulesTestContext, che si comporta come un client che non ha eseguito l'accesso tramite l'autenticazione. Le richieste create tramite il contesto restituito non avranno token Firebase Authentication allegati.
Utilizza l'oggetto del contesto di test restituito nei test per accedere a tutte le istanze dell'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 disattivate.
Questo metodo accetta una funzione di callback, che accetta il contesto di bypass delle regole di sicurezza e restituisce una promessa. Il contesto verrà eliminato una volta che la promessa viene risolta / rifiutata.
RulesTestEnvironment.cleanup()
Questo metodo elimina tutti i RulesTestContexts creati nell'ambiente di test e pulisce le risorse sottostanti, consentendo un'uscita pulita.
Questo metodo non modifica in alcun modo lo stato degli emulatori. Per reimpostare i dati tra i test, 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 assicura che la promessa fornita che racchiude un'operazione dell'emulatore venga 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 assicura che la promessa fornita che racchiude un'operazione dell'emulatore venga rifiutata con una violazione delle regole di sicurezza.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });Metodi specifici dell'emulatore
Vedi 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 ottiene un'istanza di Firestore per questo contesto di test. L'istanza dell'SDK Firebase JS Client restituita può essere utilizzata con le API dell'SDK client (v9 modulare o v9 compat).
Visualizzare le valutazioni delle regole
L'emulatore Cloud Firestore consente di visualizzare le richieste client nell' interfaccia utente di Emulator Suite, inclusa la traccia di 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 come è stata valutata ciascuna delle tue regole di sicurezza.
Per ottenere i report, esegui una query su un endpoint esposto sull'emulatore durante l'esecuzione. Per una versione adatta al browser, utilizza il seguente URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
Le regole vengono suddivise in espressioni e sottoespressioni su cui puoi passare il 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 devi creare esplicitamente un progetto Cloud Firestore. L'emulatore crea automaticamente qualsiasi istanza a cui si accede.
- L'Cloud Firestore emulator non funziona con il normale flusso Firebase Authentication.
Invece, nell'SDK Firebase Test, abbiamo fornito il metodo
initializeTestApp()nella libreriarules-unit-testing, che accetta un campoauth. L'handle Firebase creato utilizzando questo metodo si comporterà come se avesse eseguito l'autenticazione correttamente come qualsiasi entità fornita. Se passinull, si comporterà come un utente non autenticato (le regoleauth != nullnon andranno a buon fine, ad esempio).
Risolvere i problemi noti
Quando utilizzi l'emulatore Cloud Firestore, potresti riscontrare i seguenti problemi noti. Segui le indicazioni riportate di seguito per risolvere eventuali comportamenti irregolari. Queste note sono scritte tenendo presente la libreria di test delle unità delle regole di sicurezza, ma gli approcci generali sono applicabili a qualsiasi SDK Firebase.
Il comportamento dei test è incoerente
Se i test a volte vanno a buon fine e a volte no, anche senza modifiche ai test stessi, potrebbe essere necessario verificare che siano sequenziati correttamente.
La maggior parte delle interazioni con l'emulatore è asincrona, quindi controlla che tutto il codice asincrono sia sequenziato correttamente. Puoi correggere il sequenziamento concatenando le promesse o utilizzando la notazione await in modo esteso.
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(). - Asserzioni operative, tra cui
assertSucceedseassertFails.
I test vanno a buon fine solo la prima volta che carichi l'emulatore
L'emulatore è stateful. Memorizza tutti i dati scritti in memoria, quindi tutti i dati vengono persi quando l'emulatore viene arrestato. Se esegui più test sullo stesso ID progetto, ogni test può produrre dati che potrebbero influenzare i test successivi. Puoi utilizzare uno dei seguenti metodi per ignorare questo comportamento:
- Utilizza ID progetto univoci per ogni test. Tieni presente che, se scegli di farlo, dovrai chiamare
initializeTestEnvironmentcome parte 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 i tuoi
Cloud Firestore Security Rules non consentono. 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 le tue Cloud Firestore Security Rules consentano / neghino
correttamente i diversi casi.