Test delle unità di creazione

Firebase Local Emulator Suite semplificano la convalida completa delle funzionalità e del comportamento della tua app. È anche un ottimo strumento per verificare le configurazioni di Firebase Security Rules. Utilizza gli emulatori Firebase per eseguire e automatizzare i test delle unità in un ambiente locale. I metodi descritti in questo documento dovrebbero aiutarti a creare e automatizzare i test di unità per la tua app che convalidano il tuo Rules.

Se non lo hai ancora fatto, configura gli emulatori Firebase.

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 o "storage.rules" del file firebase.json. Se il file non esiste e non utilizzi il metodo loadFirestoreRules o "loadStorageRules" come descritto di seguito, l'emulatore considera tutti i progetti come contenenti regole aperte.
  • Anche se la maggior parte degli SDK Firebase funziona direttamente con gli emulatori, solo la libreria @firebase/rules-unit-testing supporta il auth simulato 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.

Differenze tra gli emulatori di database e la produzione

  • Non è necessario creare esplicitamente un'istanza di database. L'emulatore creerà automaticamente qualsiasi istanza di database a cui viene eseguito l'accesso.
  • Ogni nuovo database viene avviato con regole chiuse, pertanto gli utenti non amministratori non potranno leggere né scrivere.
  • A ogni database simulato vengono applicati i limiti e le quote del piano Spark (in particolare, ogni istanza è limitata a 100 connessioni simultanee).
  • Qualsiasi database accetterà la stringa "owner" come token di autenticazione amministratore.
  • Al momento gli emulatori non hanno interazioni funzionanti con altri prodotti Firebase. In particolare, il normale flusso di Firebase Authentication non funziona. In alternativa, puoi utilizzare il metodo initializeTestApp() nella libreria rules-unit-testing, che accetta un campo auth. L'oggetto Firebase creato utilizzando questo metodo si comporta come se fosse stato autenticato correttamente come qualsiasi entità fornita. Se passi null, il valore si comporterà come un utente non autenticato (ad esempio, le regole auth != null non andranno a buon fine).

Interazione con l'emulatore Realtime Database

Un'istanza Realtime Database Firebase di produzione è accessibile da un sottodominio di firebaseio.com e puoi accedere all'API REST come segue:

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

L'emulatore viene eseguito localmente ed è disponibile all'indirizzo localhost:9000. Per interagire con un'istanza del database specifica, dovrai utilizzare il parametro di query ns per specificare il nome del database.

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

Eseguire test locali delle unità con l'SDK JavaScript versione 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.

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 a initializeTestEnvironment.
  • Configurare i dati di test senza attivare Rules, utilizzando un metodo di comodità che consente di ignorarli 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() o RulesTestEnvironment.clearFirestore().
  • Implementazione di casi di test che simulano gli stati di autenticazione utilizzando RulesTestEnvironment.authenticatedContext e RulesTestEnvironment.unauthenticatedContext.

Metodi e funzioni di utilità comuni

Consulta anche metodi di test specifici per l'emulatore che utilizzano l'API modulare.

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 Authentication autenticato. Alle richieste create tramite il contesto restituito verrà allegato un token Authentication simulato. Se vuoi, puoi passare un oggetto che definisce rivendicazioni personalizzate o superamenti per i payload dei token Authentication.

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 client che non ha eseguito l'accesso tramite Authentication. 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 metodi di test e funzioni di utilità comuni che utilizzano l'API modulare.

Cloud Firestore

Cloud Firestore

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).

Realtime Database

Realtime Database

RulesTestEnvironment.clearDatabase() => Promise<void>

Questo metodo cancella i dati in Realtime Database che appartengono al projectId configurato per l'emulatore Realtime Database.

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

Recupera un'istanza di Realtime Database per questo contesto di test. L'istanza dell'SDK client Firebase JS restituita può essere utilizzata con le API dell'SDK client (modulari o con nome, versione 9 o successive). Il metodo accetta un URL dell'istanza Database in tempo reale. Se specificato, restituisce un'istanza per una versione emulata dello spazio dei nomi con i parametri estratti dall'URL.

Cloud Storage

Cloud Storage

RulesTestEnvironment.clearStorage() => Promise<void>

Questo metodo cancella gli oggetti e i metadati nei bucket di archiviazione appartenenti al projectId configurato per l'emulatore Cloud Storage.

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

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

Eseguire test locali delle unità con l'SDK JavaScript v8

Seleziona un prodotto per visualizzare i metodi utilizzati dall'SDK di test di Firebase per interagire 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 specificata nelle opzioni. Utilizzalo per creare un'app autenticata come utente specifico da utilizzare 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 di amministrazione inizializzata. Questa app ignora le regole di sicurezza durante l'esecuzione di letture e scritture. Utilizzalo 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 app di test e di amministrazione attualmente inizializzate. Utilizzalo 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 stringa. Utilizza questo metodo per impostare le regole del database.

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

assertFails(pr: Promise) => Promise

Questo metodo restituisce una promessa rifiutata se l'input va a buon fine o che va a buon fine se l'input viene rifiutato. Utilizzalo per verificare se una lettura o scrittura del database non va a buon fine.

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. Utilizzalo per verificare se una lettura o scrittura del database è andata a buon fine.

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

clearFirestoreData({ projectId: string }) => Promise

Questo metodo cancella tutti i dati associati a un determinato progetto nell'istanza Firestore in esecuzione localmente. Utilizza questo metodo per la pulizia dopo i test.

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

Realtime Database

Realtime Database

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

Utilizzalo per creare un'app autenticata come utente specifico da utilizzare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del database e all'override della variabile di autenticazione specificata in options.

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

initializeAdminApp({ databaseName: string }) => FirebaseApp

Utilizzalo per creare un'app autenticata come amministratore per configurare lo stato per i test.

Restituisce un'app Firebase di amministrazione inizializzata corrispondente al nome del database specificato in options. Questa app aggira le regole di sicurezza durante la lettura e la scrittura nel database.

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

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

Utilizzalo per impostare le regole del database.

Invia le regole a un database in esecuzione localmente. Accetta un oggetto opzioni che specifica "databaseName" e "rules" come stringhe.

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

apps() => [FirebaseApp]

Restituisce tutte le app di test e di amministrazione attualmente inizializzate.

Utilizza questo metodo per ripulire le app tra o dopo i test (tieni presente che le app inizializzate con ascoltatori attivi impediscono a JavaScript di uscire):

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

assertFails(pr: Promise) => Promise

Restituisce una promessa rifiutata se l'input va a buon fine e accolta se l'input viene rifiutato.

Utilizza questa istruzione per verificare che la lettura o la scrittura di un database non vada a buon fine:

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.

Utilizza questa istruzione per verificare che una lettura o scrittura del database sia andata a buon fine:

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

Cloud Storage

Cloud Storage

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

Utilizzalo per creare un'app autenticata come utente specifico da utilizzare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del bucket di archiviazione e alla sostituzione della variabile di autenticazione specificata nelle opzioni.

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

initializeAdminApp({ storageBucket: string }) => FirebaseApp

Utilizzalo per creare un'app autenticata come amministratore per configurare lo stato per i test.

Restituisce un'app Firebase di amministrazione inizializzata corrispondente al nome del bucket di archiviazione specificato in options. Questa app aggira le regole di sicurezza durante la lettura e la scrittura nel bucket.

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

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

Utilizzalo per impostare le regole del bucket di archiviazione.

Invia regole a bucket di archiviazione gestiti localmente. Prende un oggetto options che specifica "storageBucket" e "rules" come stringhe.

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

apps() => [FirebaseApp]

Restituisce tutte le app di test e di amministrazione attualmente inizializzate.

Utilizza questo metodo per ripulire le app tra o dopo i test (tieni presente che le app inizializzate con ascoltatori attivi impediscono a JavaScript di uscire):

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

assertFails(pr: Promise) => Promise

Restituisce una promessa rifiutata se l'input va a buon fine e accolta se l'input viene rifiutato.

Utilizza questo parametro per verificare che la lettura o la scrittura di un bucket di archiviazione non vada a buon fine:

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.

Utilizza questo metodo per verificare che la lettura o la scrittura di un bucket di archiviazione sia andata a buon fine:

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

API della libreria RUT per JS SDK v8

Seleziona un prodotto per visualizzare i metodi utilizzati dall'SDK di test di Firebase per interagire 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 specificata nelle opzioni. Utilizzalo per creare un'app autenticata come utente specifico da utilizzare 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 di amministrazione inizializzata. Questa app ignora le regole di sicurezza durante l'esecuzione di letture e scritture. Utilizzalo 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 app di test e di amministrazione attualmente inizializzate. Utilizzalo 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 stringa. Utilizza questo metodo per impostare le regole del database.

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

assertFails(pr: Promise) => Promise

Questo metodo restituisce una promessa rifiutata se l'input va a buon fine o che va a buon fine se l'input viene rifiutato. Utilizzalo per verificare se una lettura o scrittura del database non va a buon fine.

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. Utilizzalo per verificare se una lettura o scrittura del database è andata a buon fine.

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

clearFirestoreData({ projectId: string }) => Promise

Questo metodo cancella tutti i dati associati a un determinato progetto nell'istanza Firestore in esecuzione localmente. Utilizza questo metodo per la pulizia dopo i test.

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

Realtime Database

Realtime Database

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

Utilizzalo per creare un'app autenticata come utente specifico da utilizzare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del database e all'override della variabile di autenticazione specificata in options.

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

initializeAdminApp({ databaseName: string }) => FirebaseApp

Utilizzalo per creare un'app autenticata come amministratore per configurare lo stato per i test.

Restituisce un'app Firebase di amministrazione inizializzata corrispondente al nome del database specificato in options. Questa app aggira le regole di sicurezza durante la lettura e la scrittura nel database.

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

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

Utilizzalo per impostare le regole del database.

Invia le regole a un database in esecuzione localmente. Accetta un oggetto opzioni che specifica "databaseName" e "rules" come stringhe.

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

apps() => [FirebaseApp]

Restituisce tutte le app di test e di amministrazione attualmente inizializzate.

Utilizza questo metodo per ripulire le app tra o dopo i test (tieni presente che le app inizializzate con ascoltatori attivi impediscono a JavaScript di uscire):

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

assertFails(pr: Promise) => Promise

Restituisce una promessa rifiutata se l'input va a buon fine e accolta se l'input viene rifiutato.

Utilizza questa istruzione per verificare che la lettura o la scrittura di un database non vada a buon fine:

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.

Utilizza questa istruzione per verificare che una lettura o scrittura del database sia andata a buon fine:

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

Cloud Storage

Cloud Storage

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

Utilizzalo per creare un'app autenticata come utente specifico da utilizzare nei test.

Restituisce un'app Firebase inizializzata corrispondente al nome del bucket di archiviazione e alla sostituzione della variabile di autenticazione specificata nelle opzioni.

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

initializeAdminApp({ storageBucket: string }) => FirebaseApp

Utilizzalo per creare un'app autenticata come amministratore per configurare lo stato per i test.

Restituisce un'app Firebase di amministrazione inizializzata corrispondente al nome del bucket di archiviazione specificato in options. Questa app aggira le regole di sicurezza durante la lettura e la scrittura nel bucket.

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

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

Utilizzalo per impostare le regole del bucket di archiviazione.

Invia regole a bucket di archiviazione gestiti localmente. Prende un oggetto options che specifica "storageBucket" e "rules" come stringhe.

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

apps() => [FirebaseApp]

Restituisce tutte le app di test e di amministrazione attualmente inizializzate.

Utilizza questo metodo per ripulire le app tra o dopo i test (tieni presente che le app inizializzate con ascoltatori attivi impediscono a JavaScript di uscire):

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

assertFails(pr: Promise) => Promise

Restituisce una promessa rifiutata se l'input va a buon fine e accolta se l'input viene rifiutato.

Utilizza questo parametro per verificare che la lettura o la scrittura di un bucket di archiviazione non vada a buon fine:

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.

Utilizza questo metodo per verificare che la lettura o la scrittura di un bucket di archiviazione sia andata a buon fine:

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