Crea unit test unit

L'emulatore Suite Firebase locale rendono più facile per convalidare pienamente della tua app caratteristiche e comportamenti . È anche un ottimo strumento per verificare le configurazioni delle regole di sicurezza di Firebase. Usa gli emulatori Firebase per eseguire e automatizzare i test di unità in un ambiente locale. I metodi descritti in questo documento dovrebbero aiutarti durante la creazione e l'automazione di unit test per la tua app che convalidano le tue regole.

Se non l'hai già, impostare la Firebase emulatori .

Prima di eseguire l'emulatore

Prima di iniziare a utilizzare l'emulatore, tieni presente quanto segue:

  • L'emulatore inizialmente caricare le regole specificate nelle firestore.rules o campo '' storage.rules del firebase.json file. Se il file non esiste e non si utilizza le loadFirestoreRules o metodo 'loadStorageRules' come descritto di seguito, l'emulatore tratta tutti i progetti come avere regole aperte.
  • Mentre la maggior parte Firebase SDK lavoro con gli emulatori direttamente, solo il @firebase/rules-unit-testing supporti biblioteca beffardi auth nelle regole di sicurezza, facendo unit test molto più facile. Inoltre, la libreria supporta alcune funzionalità specifiche dell'emulatore come la cancellazione di tutti i dati, come elencato di seguito.
  • Gli emulatori accetteranno anche i token di autenticazione Firebase di produzione forniti tramite Client SDK e valuteranno le regole di conseguenza, il che consente di connettere l'applicazione direttamente agli emulatori nei test di integrazione e manuali.

Differenze tra gli emulatori di database e la produzione

  • Non è necessario creare in modo esplicito un'istanza di database. L'emulatore creerà automaticamente qualsiasi istanza di database a cui si accede.
  • Ogni nuovo database viene avviato con regole chiuse, quindi gli utenti non amministratori non saranno in grado di leggere o scrivere.
  • Ogni database emulato applica le piano Spark limiti e quote (in particolare, ciò limita ciascuna istanza a 100 connessioni simultanee).
  • Qualsiasi database accetterà la stringa "owner" come amministratore di autenticazione token.
  • Gli emulatori non hanno attualmente interazioni funzionanti con altri prodotti Firebase. In particolare, il normale flusso di autenticazione Firebase non funziona. Invece, è possibile utilizzare initializeTestApp() metodo nella rules-unit-testing biblioteca, che prende un auth campo. L'oggetto Firebase creato utilizzando questo metodo si comporta come se fosse stato autenticato correttamente come qualsiasi entità fornita. Se si passa a null , si comporterà come un utente non autenticato ( auth != null regole non riuscirà, per esempio).

Interazione con l'emulatore di database in tempo reale

Una produzione Firebase in tempo reale esempio di database è accessibile a un sottodominio di firebaseio.com , ed è possibile accedere l'API REST in questo modo:

https://<database_name>.firebaseio.com/path/to/my/data.json

L'emulatore funziona a livello locale, ed è disponibile a localhost:9000 . Per interagire con un'istanza database specifico, si dovrà utilizzare i ns parametro di query per specificare il nome del database.

http://localhost:9000/path/to/my/data.json?ns=<database_name>

Esegui unit test locali con JavaScript SDK versione 9

Firebase distribuisce una libreria di unit test delle regole di sicurezza sia con l'SDK JavaScript versione 9 che con l'SDK versione 8. Le API della libreria sono significativamente 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à a ritroso, continuiamo a fare la libreria di test v8 disponibili .

Utilizzare l' @firebase/rules-unit-testing del modulo di interagire con l'emulatore che corre a livello locale. Se si ottiene timeout o ECONNREFUSED errori, controllare che l'emulatore è effettivamente in esecuzione.

Si consiglia vivamente di utilizzare una versione recente di Node.js modo da poter utilizzare async/await la notazione. Quasi tutto il comportamento che potresti voler testare coinvolge funzioni asincrone e il modulo di test è progettato per funzionare con codice basato su Promise.

La libreria v9 Rules Unit Testing è sempre a conoscenza degli emulatori e non tocca mai le tue risorse di produzione.

Si importa la libreria utilizzando istruzioni di importazione modulare v9. Per esempio:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
  RulesTestEnvironment,
} 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 degli unit test comporta:

  • Creazione e configurazione di un RulesTestEnvironment con una chiamata a initializeTestEnvironment .
  • Impostazione di dati di test senza attivare regole, utilizzando un metodo comodo che permette di by-pass temporaneo loro, RulesTestEnvironment.withSecurityRulesDisabled .
  • Impostazione di suite di test e per-test prima / dopo ganci con le chiamate per ripulire i dati di prova e l'ambiente, come RulesTestEnvironment.cleanup() o RulesTestEnvironment.clearFirestore() .
  • Implementazione di casi di test che simulano gli stati di autenticazione utilizzando RulesTestEnvironment.authenticatedContext e RulesTestEnvironment.unauthenticatedContext .

Metodi comuni e funzioni di utilità

Vedere anche i metodi di prova specifici per emulatore nel SDK v9 .

initializeTestEnvironment() => RulesTestEnvironment

Questa funzione inizializza un ambiente di test per l'unità di test delle regole. Chiamare prima questa funzione per l'impostazione del test. L'esecuzione corretta richiede che gli emulatori siano in esecuzione.

La funzione accetta un oggetto opzionale definente una TestEnvironmentConfig , che può essere costituito da un ID progetto e emulatore impostazioni di configurazione.

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 autenticazione. Le richieste create tramite il contesto restituito avranno un token di autenticazione fittizio allegato. Facoltativamente, passare un oggetto che definisce attestazioni personalizzate o sostituzioni per i payload del token di autenticazione.

Utilizzare l'oggetto contesto di misura restituiti nei test per accedere a qualsiasi istanze dell'emulatore configurate, compresi quelli configurati 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 client che non è connesso in via di autenticazione. Le richieste create tramite il contesto restituito non avranno token di autenticazione Firebase allegati.

Utilizzare l'oggetto contesto di misura restituiti nei test per accedere a qualsiasi istanze dell'emulatore configurate, compresi quelli configurati 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()

Eseguire una funzione di configurazione di prova 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 bypass delle regole di sicurezza e restituisce una promessa. Il contesto verrà distrutto una volta che la promessa si risolve/rifiuta.

RulesTestEnvironment.cleanup()

Questo metodo distrugge tutti RulesTestContexts creati in ambiente di prova e pulisce le risorse di base, permettendo un'uscita pulita.

Questo metodo non modifica in alcun modo lo stato degli emulatori. Per ripristinare i dati tra i test, utilizzare il metodo di cancellazione dei dati specifico dell'emulatore dell'applicazione.

assertSucceeds(pr: Promise<any>)) => Promise<any>

Questa è una funzione di utilità del caso di test.

La funzione afferma che il Promise fornito che avvolge un'operazione dell'emulatore verrà risolto senza violazioni delle regole di sicurezza.

await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

assertFails(pr: Promise<any>)) => Promise<any>

Questa è una funzione di utilità del caso di test.

La funzione afferma che il Promise fornito che avvolge un'operazione dell'emulatore verrà rifiutato con una violazione delle regole di sicurezza.

await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });

Metodi specifici dell'emulatore

Vedere anche i metodi di prova comune e funzioni di utilità nel SDK v9 .

Cloud Firestore

Cloud Firestore

RulesTestEnvironment.clearFirestore() => Promise<void>

Questo metodo cancella i dati nel database FireStore che appartiene alla projectId configurato per l'emulatore FireStore.

RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;

Questo metodo ottiene un'istanza Firestore per questo contesto di test. L'istanza di Firebase JS Client SDK restituita può essere utilizzata con le API dell'SDK client (v9 modular o v9 compat).

Database in tempo reale

Database in tempo reale

RulesTestEnvironment.clearDatabase() => Promise<void>

Questo metodo cancella i dati nella base di dati in tempo reale che appartiene al projectId configurato per l'emulatore base di dati in tempo reale.

RulesTestContext.database(databaseURL?: Firestore.FirestoreSettings) => Firestore;

Ottieni un'istanza di Realtime Database per questo contesto di test. L'istanza di Firebase JS Client SDK restituita può essere utilizzata con le API dell'SDK client (v9 modular o v9 compat). Il metodo accetta un URL dell'istanza di Realtime Database. Se specificato, restituisce un'istanza per una versione emulata dello spazio dei nomi con i parametri estratti dall'URL.

Archiviazione cloud

Archiviazione cloud

RulesTestEnvironment.clearStorage() => Promise<void>

Questo metodo cancella gli oggetti ei metadati in secchi di stoccaggio del projectId configurato per l'emulatore Cloud Storage.

RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;

Questo metodo restituisce un'istanza di archiviazione configurata per connettersi all'emulatore. Il metodo accetta un gs:// URL del Firebase bagagli benna per il test. Se specificato, restituisce un'istanza di archiviazione per una versione emulata del nome del bucket.

Esegui unit test locali con JavaScript SDK v8

Seleziona un prodotto per vedere i metodi utilizzati da Firebase Test SDK per interfacciarsi con l'emulatore.

Cloud Firestore

initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp

Questo metodo restituisce un'app Firebase inizializzata corrispondente all'ID progetto e alla variabile di autenticazione specificati nelle opzioni. Usalo per creare un'app autenticata come utente specifico da usare nei test.

firebase.initializeTestApp({
  projectId: "my-test-project",
  auth: { uid: "alice", email: "alice@example.com" }
});

initializeAdminApp({ projectId: string }) => FirebaseApp

Questo metodo restituisce un'app Firebase amministratore inizializzata. Questa app ignora le regole di sicurezza durante l'esecuzione di letture e scritture. Usalo per creare un'app autenticata come amministratore per impostare lo stato per i test.

firebase.initializeAdminApp({ projectId: "my-test-project" });
    

apps() => [FirebaseApp] Questo metodo restituisce tutte le applicazioni di test e di amministrazione attualmente inizializzati. Usalo per ripulire le app tra o dopo i test.

Promise.all(firebase.apps().map(app => app.delete()))

loadFirestoreRules({ projectId: string, rules: Object }) => Promise

Questo metodo invia le regole a un database in esecuzione localmente. Prende un oggetto che specifica le regole come una stringa. Usa questo metodo per impostare le regole del tuo database.

firebase.loadFirestoreRules({
  projectId: "my-test-project",
  rules: fs.readFileSync("/path/to/firestore.rules", "utf8")
});
    

assertFails(pr: Promise) => Promise

Questo metodo restituisce una promessa che viene rifiutata se l'input ha esito positivo o che ha esito positivo se l'input viene rifiutato. Usalo per asserire se la lettura o la scrittura di un database fallisce.

firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
    

assertSucceeds(pr: Promise) => Promise

Questo metodo restituisce una promessa che ha esito positivo se l'input ha esito positivo e viene rifiutata se l'input viene rifiutato. Usalo per asserire se una lettura o una scrittura del database ha esito positivo.

firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
    

clearFirestoreData({ projectId: string }) => Promise

Questo metodo cancella tutti i dati associati a un particolare progetto nell'istanza Firestore in esecuzione in locale. Utilizzare questo metodo per pulire dopo i test.

firebase.clearFirestoreData({
  projectId: "my-test-project"
});
   

Database in tempo reale

Database in tempo reale

initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp

Usalo per creare un'app autenticata come utente specifico da usare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del database e all'override della variabile di autenticazione specificati nelle opzioni.

firebase.initializeTestApp({
  databaseName: "my-database",
  auth: { uid: "alice" }
});

initializeAdminApp({ databaseName: string }) => FirebaseApp

Usalo per creare un'app autenticata come amministratore per impostare lo stato per i test.

Restituisce un'app Firebase amministratore inizializzata corrispondente al nome del database specificato nelle opzioni. Questa app ignora le regole di sicurezza durante la lettura e la scrittura nel database.

firebase.initializeAdminApp({ databaseName: "my-database" });

loadDatabaseRules({ databaseName: string, rules: Object }) => Promise

Usalo per impostare le regole del tuo database.

Invia le regole a un database in esecuzione localmente. Accetta un oggetto options che specifica il tuo "databaseName" e le tue "regole" come stringhe.

firebase
      .loadDatabaseRules({
        databaseName: "my-database",
        rules: "{'rules': {'.read': false, '.write': false}}"
      });

apps() => [FirebaseApp]

Restituisce tutte le app di test e amministrazione attualmente inizializzate.

Usalo per ripulire le app tra o dopo i test (nota che le app inizializzate con listener attivi impediscono l'uscita da JavaScript):

 Promise.all(firebase.apps().map(app => app.delete()))

assertFails(pr: Promise) => Promise

Restituisce una promessa che viene rifiutata se l'input ha esito positivo e ha esito positivo se l'input viene rifiutato.

Usa questo per asserire che una lettura o una scrittura del database fallisce:

firebase.assertFails(app.database().ref("secret").once("value"));

assertSucceeds(pr: Promise) => Promise

Restituisce una promessa che ha esito positivo se l'input ha esito positivo e viene rifiutata se l'input viene rifiutato.

Usa questo per affermare che una lettura o una scrittura del database ha esito positivo:

firebase.assertSucceeds(app.database().ref("public").once("value"));

Archiviazione cloud

Archiviazione cloud

initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp

Usalo per creare un'app autenticata come utente specifico da usare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del bucket di archiviazione e all'override della variabile di autenticazione specificati nelle opzioni.

firebase.initializeTestApp({
  storageBucket: "my-bucket",
  auth: { uid: "alice" }
});

initializeAdminApp({ storageBucket: string }) => FirebaseApp

Usalo per creare un'app autenticata come amministratore per impostare lo stato per i test.

Restituisce un'app Firebase amministratore inizializzata corrispondente al nome del bucket di archiviazione specificato nelle opzioni. Questa app ignora le regole di sicurezza durante la lettura e la scrittura nel bucket.

firebase.initializeAdminApp({ storageBucket: "my-bucket" });

loadStorageRules({ storageBucket: string, rules: Object }) => Promise

Usalo per impostare le regole del tuo bucket di archiviazione.

Invia le regole a un bucket di archiviazione gestito localmente. Accetta un oggetto options che specifica il tuo "storageBucket" e le tue "regole" come stringhe.

firebase
      .loadStorageRules({
        storageBucket: "my-bucket",
        rules: fs.readFileSync("/path/to/storage.rules", "utf8")
      });

apps() => [FirebaseApp]

Restituisce tutte le app di test e amministrazione attualmente inizializzate.

Usalo per ripulire le app tra o dopo i test (nota che le app inizializzate con listener attivi impediscono l'uscita da JavaScript):

 Promise.all(firebase.apps().map(app => app.delete()))

assertFails(pr: Promise) => Promise

Restituisce una promessa che viene rifiutata se l'input ha esito positivo e ha esito positivo se l'input viene rifiutato.

Usa questo per affermare che la lettura o la scrittura di un bucket di archiviazione non riesce:

firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());

assertSucceeds(pr: Promise) => Promise

Restituisce una promessa che ha esito positivo se l'input ha esito positivo e viene rifiutata se l'input viene rifiutato.

Usa questo per affermare che una lettura o una scrittura di un bucket di archiviazione ha esito positivo:

firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());

API della libreria RUT per JS SDK v8

Seleziona un prodotto per vedere i metodi utilizzati da Firebase Test SDK per interfacciarsi con l'emulatore.

Cloud Firestore

Cloud Firestore

initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp

Questo metodo restituisce un'app Firebase inizializzata corrispondente all'ID progetto e alla variabile di autenticazione specificati nelle opzioni. Usalo per creare un'app autenticata come utente specifico da usare nei test.

firebase.initializeTestApp({
  projectId: "my-test-project",
  auth: { uid: "alice", email: "alice@example.com" }
});

initializeAdminApp({ projectId: string }) => FirebaseApp

Questo metodo restituisce un'app Firebase amministratore inizializzata. Questa app ignora le regole di sicurezza durante l'esecuzione di letture e scritture. Usalo per creare un'app autenticata come amministratore per impostare lo stato per i test.

firebase.initializeAdminApp({ projectId: "my-test-project" });
    

apps() => [FirebaseApp] Questo metodo restituisce tutte le applicazioni di test e di amministrazione attualmente inizializzati. Usalo per ripulire le app tra o dopo i test.

Promise.all(firebase.apps().map(app => app.delete()))

loadFirestoreRules({ projectId: string, rules: Object }) => Promise

Questo metodo invia le regole a un database in esecuzione localmente. Prende un oggetto che specifica le regole come una stringa. Usa questo metodo per impostare le regole del tuo database.

firebase.loadFirestoreRules({
  projectId: "my-test-project",
  rules: fs.readFileSync("/path/to/firestore.rules", "utf8")
});
    

assertFails(pr: Promise) => Promise

Questo metodo restituisce una promessa che viene rifiutata se l'input ha esito positivo o che ha esito positivo se l'input viene rifiutato. Usalo per asserire se la lettura o la scrittura di un database fallisce.

firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
    

assertSucceeds(pr: Promise) => Promise

Questo metodo restituisce una promessa che ha esito positivo se l'input ha esito positivo e viene rifiutata se l'input viene rifiutato. Usalo per affermare se una lettura o una scrittura del database ha esito positivo.

firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
    

clearFirestoreData({ projectId: string }) => Promise

Questo metodo cancella tutti i dati associati a un particolare progetto nell'istanza Firestore in esecuzione in locale. Utilizzare questo metodo per pulire dopo i test.

firebase.clearFirestoreData({
  projectId: "my-test-project"
});
   

Database in tempo reale

Database in tempo reale

initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp

Usalo per creare un'app autenticata come utente specifico da usare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del database e all'override della variabile di autenticazione specificati nelle opzioni.

firebase.initializeTestApp({
  databaseName: "my-database",
  auth: { uid: "alice" }
});

initializeAdminApp({ databaseName: string }) => FirebaseApp

Usalo per creare un'app autenticata come amministratore per impostare lo stato per i test.

Restituisce un'app Firebase amministratore inizializzata corrispondente al nome del database specificato nelle opzioni. Questa app ignora le regole di sicurezza durante la lettura e la scrittura nel database.

firebase.initializeAdminApp({ databaseName: "my-database" });

loadDatabaseRules({ databaseName: string, rules: Object }) => Promise

Usalo per impostare le regole del tuo database.

Invia le regole a un database in esecuzione localmente. Accetta un oggetto options che specifica il tuo "databaseName" e le tue "regole" come stringhe.

firebase
      .loadDatabaseRules({
        databaseName: "my-database",
        rules: "{'rules': {'.read': false, '.write': false}}"
      });

apps() => [FirebaseApp]

Restituisce tutte le app di test e amministrazione attualmente inizializzate.

Usalo per ripulire le app tra o dopo i test (nota che le app inizializzate con listener attivi impediscono l'uscita da JavaScript):

 Promise.all(firebase.apps().map(app => app.delete()))

assertFails(pr: Promise) => Promise

Restituisce una promessa che viene rifiutata se l'input ha esito positivo e ha esito positivo se l'input viene rifiutato.

Usa questo per asserire che una lettura o una scrittura del database fallisce:

firebase.assertFails(app.database().ref("secret").once("value"));

assertSucceeds(pr: Promise) => Promise

Restituisce una promessa che ha esito positivo se l'input ha esito positivo e viene rifiutata se l'input viene rifiutato.

Usa questo per affermare che una lettura o una scrittura del database ha esito positivo:

firebase.assertSucceeds(app.database().ref("public").once("value"));

Archiviazione cloud

Archiviazione cloud

initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp

Usalo per creare un'app autenticata come utente specifico da usare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del bucket di archiviazione e all'override della variabile di autenticazione specificati nelle opzioni.

firebase.initializeTestApp({
  storageBucket: "my-bucket",
  auth: { uid: "alice" }
});

initializeAdminApp({ storageBucket: string }) => FirebaseApp

Usalo per creare un'app autenticata come amministratore per impostare lo stato per i test.

Restituisce un'app Firebase amministratore inizializzata corrispondente al nome del bucket di archiviazione specificato nelle opzioni. Questa app ignora le regole di sicurezza durante la lettura e la scrittura nel bucket.

firebase.initializeAdminApp({ storageBucket: "my-bucket" });

loadStorageRules({ storageBucket: string, rules: Object }) => Promise

Usalo per impostare le regole del tuo bucket di archiviazione.

Invia le regole a un bucket di archiviazione gestito localmente. Accetta un oggetto options che specifica il tuo "storageBucket" e le tue "regole" come stringhe.

firebase
      .loadStorageRules({
        storageBucket: "my-bucket",
        rules: fs.readFileSync("/path/to/storage.rules", "utf8")
      });

apps() => [FirebaseApp]

Restituisce tutte le app di test e amministrazione attualmente inizializzate.

Usalo per ripulire le app tra o dopo i test (nota che le app inizializzate con listener attivi impediscono l'uscita di JavaScript):

 Promise.all(firebase.apps().map(app => app.delete()))

assertFails(pr: Promise) => Promise

Restituisce una promessa che viene rifiutata se l'input ha esito positivo e ha esito positivo se l'input viene rifiutato.

Usa questo per affermare che la lettura o la scrittura di un bucket di archiviazione non riesce:

firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());

assertSucceeds(pr: Promise) => Promise

Restituisce una promessa che ha esito positivo se l'input ha esito positivo e viene rifiutata se l'input viene rifiutato.

Usa questo per affermare che una lettura o una scrittura di un bucket di archiviazione ha esito positivo:

firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());