Con Firebase Local Emulator Suite es más sencillo validar por completo las funciones y el comportamiento de tu app. Además, es una herramienta excelente para verificar tu configuración de reglas de seguridad de Firebase. Usa los emuladores de Firebase para ejecutar y automatizar pruebas de unidades en un entorno local. Los métodos descritos en este documento te pueden ayudar con la compilación y automatización de pruebas de unidades para tu app que validen las reglas aplicadas.
Si aún no lo has hecho, configura los emuladores de Firebase.
Antes de que ejecutes el emulador
Antes de comenzar a usar el emulador, ten en cuenta lo siguiente:
- Inicialmente, el emulador cargará las reglas especificadas en los campos
firestore.rules
o “storage.rules” de tu archivofirebase.json
. Si el archivo no existe y no usas los métodosloadFirestoreRules
o “loadStorageRules” como se describe a continuación, el emulador trata todos los proyectos como si tuvieran reglas abiertas. - Si bien
la mayoría de los SDKs de Firebase
funcionan con los emuladores de forma directa, solo la biblioteca
@firebase/rules-unit-testing
admite la simulación deauth
en las reglas de seguridad, lo que facilita las pruebas de unidades. Además, la biblioteca admite algunas funciones específicas del emulador, como borrar todos los datos, según se detalla a continuación. - Los emuladores también aceptarán tokens de producción de Firebase Auth proporcionados a través de SDK cliente y evaluarán las reglas en consecuencia, lo que te permite conectar tu aplicación directamente a los emuladores en pruebas de integración y manuales.
Diferencias entre los emuladores de bases de datos y la producción
- No es necesario crear una instancia de base de datos de manera explícita. El emulador creará automáticamente cualquier instancia de base de datos a la que se acceda.
- Cada base de datos nueva se inicia con reglas cerradas, por lo que los usuarios que no sean administradores no podrán realizar operaciones de lectura ni escritura.
- Se aplican los límites y cuotas del plan Spark a todas las bases de datos emuladas (en particular, esto limita cada instancia a 100 conexiones simultáneas).
- Cualquier base de datos aceptará la string
"owner"
como token de autenticación del administrador. - Actualmente los emuladores no tienen interacciones operativas con otros productos de Firebase. En particular, no funciona el flujo normal de Firebase Authentication.
En su lugar, puedes usar el método
initializeTestApp()
en la bibliotecarules-unit-testing
, que emplea un campoauth
. El objeto de Firebase que se cree con este método se comportará como si se autenticara correctamente al igual que cualquier entidad proporcionada. Si pasasnull
, se comportará como un usuario no autenticado (por ejemplo, fallarán las reglasauth != null
).
Interactúa con el emulador de Realtime Database
Se puede acceder a una instancia de producción de Firebase Realtime Database en un subdominio de firebaseio.com
, y puedes acceder a la API de REST de la siguiente manera:
https://<database_name>.firebaseio.com/path/to/my/data.json
El emulador se ejecuta de manera local y está disponible en localhost:9000
. Para interactuar
con una instancia de base de datos específica, deberás usar el parámetro de búsqueda ns
a fin de especificar el nombre de la base de datos.
http://localhost:9000/path/to/my/data.json?ns=<database_name>
Ejecuta pruebas de unidades locales con el SDK de JavaScript de la versión 9
Firebase distribuye una biblioteca de pruebas de unidades de reglas de seguridad con el SDK de JavaScript de la versión 9 y el SDK de la versión 8. Las APIs de la biblioteca son muy diferentes. Recomendamos la biblioteca de prueba de la versión 9, que es más optimizada y requiere menos configuración para conectarse a los emuladores y, por lo tanto, evitar de forma segura el uso accidental de recursos de producción. Para la retrocompatibilidad, seguimos ofreciendo la biblioteca de pruebas de la versión 8.
- Métodos de prueba y funciones de utilidad comunes en el SDK de la versión 9
- Métodos de prueba específicos del emulador en el SDK de la versión 9
Usa el módulo @firebase/rules-unit-testing
para interactuar con el emulador
que se ejecuta de manera local. Si recibes errores ECONNREFUSED
o de tiempo de espera, vuelve a verificar que se esté ejecutando el emulador.
Recomendamos usar una versión reciente de Node.js, de modo que puedas utilizar la notación async/await
. Casi todo comportamiento que quieras probar involucra
funciones asíncronas. El módulo de pruebas está diseñado para funcionar con
código basado en promesas.
La biblioteca de pruebas de unidades de reglas de la versión 9 siempre tiene en cuenta los emuladores y nunca toca tus recursos de producción.
Importarás la biblioteca usando las instrucciones de importación de la versión 9 modular. Por ejemplo:
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.
Cuando esté importada, la implementación de pruebas de unidades implica lo siguiente:
- Crear y configurar un
RulesTestEnvironment
con una llamada ainitializeTestEnvironment
- Configurar datos de prueba sin activar reglas mediante un método
útil que te permita omitirlos temporalmente,
RulesTestEnvironment.withSecurityRulesDisabled
- Configurar paquetes de pruebas y hooks por prueba antes o después con llamadas para
limpiar los datos y el entorno de prueba, como
RulesTestEnvironment.cleanup()
oRulesTestEnvironment.clearFirestore()
- Implementar casos de prueba que imiten estados de autenticación mediante
RulesTestEnvironment.authenticatedContext
yRulesTestEnvironment.unauthenticatedContext
Métodos y funciones de utilidad comunes
Consulta también los métodos de prueba específicos del emulador con la API modular.
initializeTestEnvironment() => RulesTestEnvironment
Esta función inicializa un entorno de pruebas para la prueba de unidades de reglas. Llama a esta función primero para la configuración de prueba. Si la ejecución es correcta, se deben ejecutar emuladores.
La función acepta un objeto opcional que define una TestEnvironmentConfig
,
que puede consistir en un ID del proyecto y en parámetros de configuración del emulador.
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
Este método crea un RulesTestContext
, que se comporta como un usuario
autenticado de Authentication. Las solicitudes creadas a través del contexto mostrado tendrán un token de
autenticación ficticio adjunto. De manera opcional, pasa un objeto que defina reclamaciones personalizadas o
anule las cargas útiles del token de Authentication.
Usa en tus pruebas el objeto de contexto de prueba que se muestra para acceder a cualquier instancia
del emulador configurada, incluidas las configuradas 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
Este método crea un RulesTestContext
, que se comporta como un cliente que
no accedió mediante Authentication. Las solicitudes creadas a través del contexto mostrado no
tendrán tokens de Firebase Auth adjuntos.
Usa en tus pruebas el objeto de contexto de prueba que se muestra para acceder a cualquier instancia
del emulador configurada, incluidas las configuradas 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()
Ejecuta una función de configuración de prueba con un contexto que se comporte como si estuvieran inhabilitadas las reglas de seguridad.
Este método usa una función de devolución de llamada, que toma el contexto que omite las reglas de seguridad y muestra una promesa. El contexto se destruirá cuando la promesa se resuelva o rechace.
RulesTestEnvironment.cleanup()
Este método destruye todos los RulesTestContexts
creados en el entorno de prueba y
limpia los recursos subyacentes, lo que permite una salida limpia.
Este método no cambia el estado de los emuladores de ninguna manera. Para restablecer datos entre pruebas, usa el método de eliminación de datos específico del emulador de la aplicación.
assertSucceeds(pr: Promise<any>)) => Promise<any>
Esta es una función de utilidad de caso de prueba.
La función afirma que la promesa proporcionada de una operación del emulador se resolverá sin infringir las reglas de seguridad.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
Esta es una función de utilidad de caso de prueba.
La función afirma que la promesa proporcionada de una operación del emulador se rechazará con una infracción de las reglas de seguridad.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
Métodos específicos del emulador
Consulta también los métodos de prueba y las funciones de utilidad comunes con la API modular.
Cloud Firestore
Cloud Firestore
RulesTestEnvironment.clearFirestore() => Promise<void>
Este método borra los datos de la base de datos de Firestore que pertenecen al
projectId
configurado para el emulador de Firestore.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
Con este método, se obtiene una instancia de Firestore para este contexto de prueba. La instancia del SDK cliente de Firebase JS que se muestra se puede usar con las API del SDK cliente (compatibles con la versión 9 modular o la versión 9).
Realtime Database
Realtime Database
RulesTestEnvironment.clearDatabase() => Promise<void>
Este método borra los datos de Realtime Database que pertenecen al
projectId
configurado para el emulador de Realtime Database.
RulesTestContext.database(databaseURL?: Firestore.FirestoreSettings) => Firestore;
Obtén una instancia de Realtime Database para este contexto de prueba. La instancia del SDK cliente de Firebase JS que se muestra se puede usar con las APIs del SDK cliente (modulares o con espacio de nombres, versión 9 o posterior). El método acepta una URL de la instancia de Realtime Database. Si se especifica, muestra una instancia para una versión emulada del espacio de nombres con los parámetros extraídos de la URL.
Cloud Storage
Cloud Storage
RulesTestEnvironment.clearStorage() => Promise<void>
Este método borra objetos y metadatos en buckets de almacenamiento que pertenecen al
projectId
configurado para el emulador de Cloud Storage.
RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;
Además, muestra una instancia de Storage configurada para conectarse al emulador
y acepta una URL gs://
para enviar el bucket de Firebase Storage a fin de realizar pruebas. Si
se especifica, muestra una instancia de Storage para una versión emulada del nombre del bucket.
Ejecuta pruebas de unidades locales con el SDK de JavaScript de la versión 8
Selecciona un producto y conoce los métodos que usa el SDK de Firebase Test para interactuar con el emulador.
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Este método muestra una app de Firebase inicializada correspondiente al ID del proyecto y la variable de auth especificada en las opciones. Úsalo para crear una app autenticada como un usuario específico que puedes emplear durante las pruebas.
firebase.initializeTestApp({ projectId: "my-test-project", auth: { uid: "alice", email: "alice@example.com" } });
initializeAdminApp({ projectId: string }) => FirebaseApp
Este método muestra una app de administración de Firebase inicializada, que omite las reglas de seguridad cuando realiza operaciones de lectura y escritura. Usa el método a fin de crear una app autenticada como un administrador para configurar el estado de las pruebas.
firebase.initializeAdminApp({ projectId: "my-test-project" });
apps() => [FirebaseApp]
Este método muestra todas las apps de administración y pruebas inicializadas actualmente.
Úsalo para limpiar las apps entre pruebas o después de ellas.
Promise.all(firebase.apps().map(app => app.delete()))
loadFirestoreRules({ projectId: string, rules: Object }) => Promise
Este método envía reglas a una base de datos que se ejecuta localmente. Requiere un objeto que especifique las reglas como string. Usa este método para configurar las reglas de tu base de datos.
firebase.loadFirestoreRules({ projectId: "my-test-project", rules: fs.readFileSync("/path/to/firestore.rules", "utf8") });
assertFails(pr: Promise) => Promise
Este método muestra una promesa que se rechaza si la entrada es correcta o se cumple correctamente si la entrada se rechaza. Úsalo para confirmar si fallan las operaciones de lectura o escritura de una base de datos.
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: Promise) => Promise
Este método muestra una promesa que se cumple correctamente si la entrada es correcta o se rechaza si la entrada se rechaza. Úsalo para confirmar si se completan correctamente las operaciones de lectura o escritura de una base de datos.
firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
clearFirestoreData({ projectId: string }) => Promise
Este método borra todos los datos asociados a un proyecto determinado de la instancia de Firestore que se ejecuta de manera local. Usa este método para realizar la limpieza después de las pruebas.
firebase.clearFirestoreData({ projectId: "my-test-project" });
Realtime Database
Realtime Database
initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp
Úsalo para crear una app autenticada como un usuario específico que puedes usar durante las pruebas.
Muestra una app de Firebase inicializada correspondiente al nombre de la base de datos y la anulación de la variable auth que se especificó en las opciones.
firebase.initializeTestApp({
databaseName: "my-database",
auth: { uid: "alice" }
});
initializeAdminApp({ databaseName: string }) => FirebaseApp
Úsalo a fin de crear una app autenticada como un administrador para configurar el estado de las pruebas.
Muestra una app de administración de Firebase inicializada correspondiente al nombre de la base de datos que se especificó en las opciones. Esta app ignora las reglas de seguridad al momento de leer o escribir en la base de datos.
firebase.initializeAdminApp({ databaseName: "my-database" });
loadDatabaseRules({ databaseName: string, rules: Object }) => Promise
Úsalo para configurar las reglas de tu base de datos.
Envía reglas a una base de datos que se ejecuta localmente. Toma un objeto de opciones que indica tu “databaseName” y tus “rules” como strings.
firebase
.loadDatabaseRules({
databaseName: "my-database",
rules: "{'rules': {'.read': false, '.write': false}}"
});
apps() => [FirebaseApp]
Muestra todas las apps de administración y prueba inicializadas.
Úsalo para limpiar las apps entre pruebas o a su término (ten en cuenta que las apps inicializadas con objetos de escucha activos evitan la salida de JavaScript):
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Muestra una promesa que se rechaza si la entrada es correcta y se cumple correctamente si se rechaza la entrada.
Úsalo para confirmar que fallan las operaciones de lectura o escritura de una base de datos:
firebase.assertFails(app.database().ref("secret").once("value"));
assertSucceeds(pr: Promise) => Promise
Muestra una promesa que se cumple correctamente si la entrada es correcta y se rechaza si la entrada se rechaza.
Úsalo para declarar que una base de datos puede leer o escribir:
firebase.assertSucceeds(app.database().ref("public").once("value"));
Cloud Storage
Cloud Storage
initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp
Úsalo para crear una app autenticada como un usuario específico que puedes usar durante las pruebas.
Muestra una app de Firebase inicializada correspondiente al nombre del bucket de almacenamiento y la anulación de la variable auth que se especificó en las opciones.
firebase.initializeTestApp({
storageBucket: "my-bucket",
auth: { uid: "alice" }
});
initializeAdminApp({ storageBucket: string }) => FirebaseApp
Úsalo a fin de crear una app autenticada como un administrador para configurar el estado de las pruebas.
Muestra una app de administración de Firebase inicializada correspondiente al nombre del bucket de almacenamiento especificado en las opciones. Esta app omite las reglas de seguridad al momento de leer y escribir en el bucket.
firebase.initializeAdminApp({ storageBucket: "my-bucket" });
loadStorageRules({ storageBucket: string, rules: Object }) => Promise
Úsalo para configurar las reglas de tu bucket de almacenamiento.
Envía reglas a buckets de almacenamiento administrados de manera local. Toma un objeto de opciones que indica tu “storageBucket” y tus “reglas” como strings.
firebase
.loadStorageRules({
storageBucket: "my-bucket",
rules: fs.readFileSync("/path/to/storage.rules", "utf8")
});
apps() => [FirebaseApp]
Muestra todas las apps de administración y prueba inicializadas.
Úsalo para limpiar las apps entre pruebas o a su término (ten en cuenta que las apps inicializadas con objetos de escucha activos evitan la salida de JavaScript):
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Muestra una promesa que se rechaza si la entrada es correcta y se cumple correctamente si se rechaza la entrada.
Úsalo para confirmar que falla la lectura o escritura de un bucket de almacenamiento:
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
Muestra una promesa que se cumple correctamente si la entrada es correcta y que se rechaza si la entrada se rechaza.
Úsalo para confirmar que se logró la lectura o escritura de un bucket de almacenamiento:
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());
API de la biblioteca de pruebas de unidades de reglas para el SDK de JS de la versión 8
Selecciona un producto y conoce los métodos que usa el SDK de Firebase Test para interactuar con el emulador.
Cloud Firestore
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Este método muestra una app de Firebase inicializada correspondiente al ID del proyecto y la variable de auth especificada en las opciones. Úsalo para crear una app autenticada como un usuario específico que puedes emplear durante las pruebas.
firebase.initializeTestApp({ projectId: "my-test-project", auth: { uid: "alice", email: "alice@example.com" } });
initializeAdminApp({ projectId: string }) => FirebaseApp
Este método muestra una app de administración de Firebase inicializada, que omite las reglas de seguridad cuando realiza operaciones de lectura y escritura. Usa el método a fin de crear una app autenticada como un administrador para configurar el estado de las pruebas.
firebase.initializeAdminApp({ projectId: "my-test-project" });
apps() => [FirebaseApp]
Este método muestra todas las apps de administración y pruebas inicializadas actualmente.
Úsalo para limpiar las apps entre pruebas o después de ellas.
Promise.all(firebase.apps().map(app => app.delete()))
loadFirestoreRules({ projectId: string, rules: Object }) => Promise
Este método envía reglas a una base de datos que se ejecuta localmente. Requiere un objeto que especifique las reglas como string. Usa este método para configurar las reglas de tu base de datos.
firebase.loadFirestoreRules({ projectId: "my-test-project", rules: fs.readFileSync("/path/to/firestore.rules", "utf8") });
assertFails(pr: Promise) => Promise
Este método muestra una promesa que se rechaza si la entrada es correcta o se cumple correctamente si la entrada se rechaza. Úsalo para confirmar si fallan las operaciones de lectura o escritura de una base de datos.
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: Promise) => Promise
Este método muestra una promesa que se cumple correctamente si la entrada es correcta o se rechaza si la entrada se rechaza. Úsalo para confirmar si se completan correctamente las operaciones de lectura o escritura de una base de datos.
firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
clearFirestoreData({ projectId: string }) => Promise
Este método borra todos los datos asociados a un proyecto determinado de la instancia de Firestore que se ejecuta de manera local. Usa este método para realizar la limpieza después de las pruebas.
firebase.clearFirestoreData({ projectId: "my-test-project" });
Realtime Database
Realtime Database
initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp
Úsalo para crear una app autenticada como un usuario específico que puedes usar durante las pruebas.
Muestra una app de Firebase inicializada correspondiente al nombre de la base de datos y la anulación de la variable auth que se especificó en las opciones.
firebase.initializeTestApp({
databaseName: "my-database",
auth: { uid: "alice" }
});
initializeAdminApp({ databaseName: string }) => FirebaseApp
Úsalo a fin de crear una app autenticada como un administrador para configurar el estado de las pruebas.
Muestra una app de administración de Firebase inicializada correspondiente al nombre de la base de datos que se especificó en las opciones. Esta app ignora las reglas de seguridad al momento de leer o escribir en la base de datos.
firebase.initializeAdminApp({ databaseName: "my-database" });
loadDatabaseRules({ databaseName: string, rules: Object }) => Promise
Úsalo para configurar las reglas de tu base de datos.
Envía reglas a una base de datos que se ejecuta localmente. Toma un objeto de opciones que indica tu “databaseName” y tus “rules” como strings.
firebase
.loadDatabaseRules({
databaseName: "my-database",
rules: "{'rules': {'.read': false, '.write': false}}"
});
apps() => [FirebaseApp]
Muestra todas las apps de administración y prueba inicializadas.
Úsalo para limpiar las apps entre pruebas o a su término (ten en cuenta que las apps inicializadas con objetos de escucha activos evitan la salida de JavaScript):
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Muestra una promesa que se rechaza si la entrada es correcta y se cumple correctamente si se rechaza la entrada.
Úsalo para confirmar que fallan las operaciones de lectura o escritura de una base de datos:
firebase.assertFails(app.database().ref("secret").once("value"));
assertSucceeds(pr: Promise) => Promise
Muestra una promesa que se cumple correctamente si la entrada es correcta y se rechaza si la entrada se rechaza.
Úsalo para declarar que una base de datos puede leer o escribir:
firebase.assertSucceeds(app.database().ref("public").once("value"));
Cloud Storage
Cloud Storage
initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp
Úsalo para crear una app autenticada como un usuario específico que puedes usar durante las pruebas.
Muestra una app de Firebase inicializada correspondiente al nombre del bucket de almacenamiento y la anulación de la variable auth que se especificó en las opciones.
firebase.initializeTestApp({
storageBucket: "my-bucket",
auth: { uid: "alice" }
});
initializeAdminApp({ storageBucket: string }) => FirebaseApp
Úsalo a fin de crear una app autenticada como un administrador para configurar el estado de las pruebas.
Muestra una app de administración de Firebase inicializada correspondiente al nombre del bucket de almacenamiento especificado en las opciones. Esta app omite las reglas de seguridad al momento de leer y escribir en el bucket.
firebase.initializeAdminApp({ storageBucket: "my-bucket" });
loadStorageRules({ storageBucket: string, rules: Object }) => Promise
Úsalo para configurar las reglas de tu bucket de almacenamiento.
Envía reglas a buckets de almacenamiento administrados de manera local. Toma un objeto de opciones que indica tu “storageBucket” y tus “reglas” como strings.
firebase
.loadStorageRules({
storageBucket: "my-bucket",
rules: fs.readFileSync("/path/to/storage.rules", "utf8")
});
apps() => [FirebaseApp]
Muestra todas las apps de administración y prueba inicializadas.
Úsalo para limpiar las apps entre pruebas o a su término (ten en cuenta que las apps inicializadas con objetos de escucha activos evitan la salida de JavaScript):
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Muestra una promesa que se rechaza si la entrada es correcta y se cumple correctamente si se rechaza la entrada.
Úsalo para confirmar que falla la lectura o escritura de un bucket de almacenamiento:
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
Muestra una promesa que se cumple correctamente si la entrada es correcta y que se rechaza si la entrada se rechaza.
Úsalo para confirmar que se logró la lectura o escritura de un bucket de almacenamiento:
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());