Mientras crea su aplicación, es posible que desee bloquear el acceso a su base de datos de Cloud Firestore. Sin embargo, antes del lanzamiento, necesitará reglas de seguridad de Cloud Firestore más matizadas. Con el emulador de Cloud Firestore, además de crear prototipos y probar las características y el comportamiento generales de su aplicación, puede escribir pruebas unitarias que verifiquen el comportamiento de sus reglas de seguridad de Cloud Firestore.
Inicio rápido
Para ver algunos casos de prueba básicos con reglas simples, pruebe el ejemplo de inicio rápido .
Comprender las reglas de seguridad de Cloud Firestore
Implemente las reglas de seguridad de Firebase Authentication y Cloud Firestore para la autenticación, autorización y validación de datos sin servidor cuando utilice las bibliotecas de clientes web y móviles.
Las reglas de seguridad de Cloud Firestore incluyen dos partes:
- Una declaración
match
que identifica los documentos en su base de datos. - Una expresión
allow
que controla el acceso a esos documentos.
Firebase Authentication verifica las credenciales de los usuarios y proporciona la base para sistemas de acceso basados en usuarios y roles.
Cada solicitud de base de datos de una biblioteca de cliente web/móvil de Cloud Firestore se evalúa según sus reglas de seguridad antes de leer o escribir cualquier dato. Si las reglas niegan el acceso a cualquiera de las rutas de documentos especificadas, toda la solicitud falla.
Obtenga más información sobre las reglas de seguridad de Cloud Firestore en Introducción a las reglas de seguridad de Cloud Firestore .
Instalar el emulador
Para instalar el emulador de Cloud Firestore, use Firebase CLI y ejecute el siguiente comando:
firebase setup:emulators:firestore
Ejecute el emulador
Comience inicializando un proyecto de Firebase en su directorio de trabajo. Este es un primer paso común cuando se utiliza Firebase CLI .
firebase init
Inicie el emulador usando el siguiente comando. El emulador se ejecutará hasta que finalices el proceso:
firebase emulators:start --only firestore
En muchos casos, desea iniciar el emulador, ejecutar un conjunto de pruebas y luego apagar el emulador después de ejecutar las pruebas. Puedes hacer esto fácilmente usando el comando emulators:exec
:
firebase emulators:exec --only firestore "./my-test-script.sh"
Cuando se inicie, el emulador intentará ejecutarse en un puerto predeterminado (8080). Puedes cambiar el puerto del emulador modificando la sección "emulators"
de tu archivo firebase.json
:
{ // ... "emulators": { "firestore": { "port": "YOUR_PORT" } } }
Antes de ejecutar el emulador
Antes de comenzar a utilizar el emulador, tenga en cuenta lo siguiente:
- El emulador cargará inicialmente las reglas especificadas en el campo
firestore.rules
de su archivofirebase.json
. Espera el nombre de un archivo local que contiene sus reglas de seguridad de Cloud Firestore y aplica esas reglas a todos los proyectos. Si no proporciona la ruta del archivo local o utiliza el métodoloadFirestoreRules
como se describe a continuación, el emulador trata todos los proyectos como si tuvieran reglas abiertas. - Si bien la mayoría de los SDK de Firebase funcionan directamente con los emuladores, solo la biblioteca
@firebase/rules-unit-testing
admiteauth
simulada en las reglas de seguridad, lo que facilita mucho las pruebas unitarias. Además, la biblioteca admite algunas funciones específicas del emulador, como borrar todos los datos, como se enumera a continuación. - Los emuladores también aceptarán tokens de Firebase Auth de producción proporcionados a través de los SDK del cliente y evaluarán las reglas en consecuencia, lo que permite conectar su aplicación directamente a los emuladores en pruebas de integración y manuales.
Ejecute pruebas de unidades locales
Ejecute pruebas de unidades locales con el SDK de JavaScript v9
Firebase distribuye una biblioteca de pruebas unitarias de reglas de seguridad con su SDK de JavaScript versión 9 y su SDK versión 8. Las API de la biblioteca son significativamente diferentes. Recomendamos la biblioteca de pruebas v9, que es más optimizada y requiere menos configuración para conectarse a emuladores y así evitar de forma segura el uso accidental de recursos de producción. Para lograr compatibilidad con versiones anteriores, seguimos poniendo a disposición la biblioteca de pruebas v8 .
- Métodos de prueba comunes y funciones de utilidad en el SDK v9
- Métodos de prueba específicos del emulador en el SDK v9
Utilice el módulo @firebase/rules-unit-testing
para interactuar con el emulador que se ejecuta localmente. Si obtiene tiempos de espera o errores ECONNREFUSED
, verifique que el emulador realmente se esté ejecutando.
Recomendamos encarecidamente utilizar una versión reciente de Node.js para poder utilizar la notación async/await
. Casi todo el comportamiento que quizás desee probar involucra funciones asincrónicas y el módulo de prueba está diseñado para funcionar con código basado en Promise.
La biblioteca de pruebas unitarias de reglas v9 siempre está al tanto de los emuladores y nunca toca sus recursos de producción.
Importa la biblioteca utilizando declaraciones de importación modulares v9. Por ejemplo:
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 vez importadas, la implementación de pruebas unitarias implica:
- Crear y configurar un
RulesTestEnvironment
con una llamada ainitializeTestEnvironment
. - Configurar datos de prueba sin activar reglas, utilizando un método conveniente que le permite omitirlas temporalmente,
RulesTestEnvironment.withSecurityRulesDisabled
. - Configurar un conjunto de pruebas y enlaces antes/después de cada prueba con llamadas para limpiar los datos y el entorno de la prueba, como
RulesTestEnvironment.cleanup()
oRulesTestEnvironment.clearFirestore()
. - Implementar casos de prueba que imitan los estados de autenticación usando
RulesTestEnvironment.authenticatedContext
yRulesTestEnvironment.unauthenticatedContext
.
Métodos comunes y funciones de utilidad.
Consulte también los métodos de prueba específicos del emulador en el SDK v9 .
initializeTestEnvironment() => RulesTestEnvironment
Esta función inicializa un entorno de prueba para pruebas unitarias de reglas. Llame a esta función primero para la configuración de la prueba. La ejecución exitosa requiere que se estén ejecutando emuladores.
La función acepta un objeto opcional que define TestEnvironmentConfig
, que puede consistir en un ID de proyecto y ajustes 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 de autenticación autenticado. Las solicitudes creadas a través del contexto devuelto tendrán adjunto un token de autenticación simulado. Opcionalmente, pase un objeto que defina notificaciones personalizadas o anulaciones para las cargas útiles del token de autenticación.
Utilice el objeto de contexto de prueba devuelto en sus pruebas para acceder a cualquier instancia del emulador configurada, incluidas aquellas 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 ha iniciado sesión mediante autenticación. Las solicitudes creadas a través del contexto devuelto no tendrán tokens de autenticación de Firebase adjuntos.
Utilice el objeto de contexto de prueba devuelto en sus pruebas para acceder a cualquier instancia del emulador configurada, incluidas aquellas 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()
Ejecute una función de configuración de prueba con un contexto que se comporte como si las reglas de seguridad estuvieran deshabilitadas.
Este método toma una función de devolución de llamada, que toma el contexto de omisión de reglas de seguridad y devuelve una promesa. El contexto se destruirá una vez que la promesa se resuelva/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, utilice el método de borrar datos específico del emulador de aplicaciones.
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 que envuelve una operación del emulador se resolverá sin violaciones de 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 que envuelve una operación del emulador será rechazada con una violación de las Reglas de Seguridad.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
Métodos específicos del emulador
Consulte también los métodos de prueba comunes y las funciones de utilidad en el SDK v9 .
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;
Este método obtiene una instancia de Firestore para este contexto de prueba. La instancia del SDK del cliente Firebase JS devuelta se puede usar con las API del SDK del cliente (v9 modular o compatible con v9).
Visualizar evaluaciones de reglas
El emulador de Cloud Firestore te permite visualizar las solicitudes de los clientes en la interfaz de usuario de Emulator Suite, incluido el seguimiento de la evaluación de las reglas de seguridad de Firebase.
Abra la pestaña Firestore > Solicitudes para ver la secuencia de evaluación detallada de cada solicitud.
Generar informes de prueba
Después de ejecutar un conjunto de pruebas, puede acceder a informes de cobertura de pruebas que muestran cómo se evaluó cada una de sus reglas de seguridad.
Para obtener los informes, consulte un punto final expuesto en el emulador mientras se está ejecutando. Para obtener una versión compatible con el navegador, utilice la siguiente URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
Esto divide sus reglas en expresiones y subexpresiones sobre las que puede pasar el mouse para obtener más información, incluida la cantidad de evaluaciones y valores devueltos. Para la versión JSON sin formato de estos datos, incluya la siguiente URL en su consulta:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
Diferencias entre el emulador y la producción.
- No es necesario crear explícitamente un proyecto de Cloud Firestore. El emulador crea automáticamente cualquier instancia a la que se accede.
- El emulador de Cloud Firestore no funciona con el flujo normal de autenticación de Firebase. En cambio, en el SDK de Firebase Test, proporcionamos el método
initializeTestApp()
en la bibliotecarules-unit-testing
, que toma un campoauth
. El identificador de Firebase creado con este método se comportará como si se hubiera autenticado correctamente como cualquier entidad que proporcione. Si pasanull
, se comportará como un usuario no autenticado (las reglasauth != null
fallarán, por ejemplo).
Solucionar problemas conocidos
Al utilizar el emulador de Cloud Firestore, es posible que se encuentre con los siguientes problemas conocidos. Siga las instrucciones a continuación para solucionar cualquier comportamiento irregular que esté experimentando. Estas notas están escritas teniendo en cuenta la biblioteca de pruebas unitarias de Reglas de seguridad, pero los enfoques generales son aplicables a cualquier SDK de Firebase.
El comportamiento de la prueba es inconsistente
Si sus pruebas ocasionalmente pasan y fallan, incluso sin realizar cambios en las pruebas mismas, es posible que deba verificar que estén secuenciadas correctamente. La mayoría de las interacciones con el emulador son asíncronas, así que verifique que todo el código asíncrono esté secuenciado correctamente. Puede arreglar la secuencia encadenando promesas o usando la notación await
generosamente.
En particular, revise las siguientes operaciones asíncronas:
- Establecer reglas de seguridad, por ejemplo, con
initializeTestEnvironment
. - Leer y escribir datos, por ejemplo, con
db.collection("users").doc("alice").get()
. - Afirmaciones operativas, incluidas
assertSucceeds
yassertFails
.
Las pruebas solo pasan la primera vez que cargas el emulador.
El emulador tiene estado. Almacena todos los datos escritos en la memoria, por lo que todos los datos se pierden cada vez que se apaga el emulador. Si ejecuta varias pruebas con el mismo ID de proyecto, cada prueba puede producir datos que podrían influir en las pruebas posteriores. Puede utilizar cualquiera de los siguientes métodos para evitar este comportamiento:
- Utilice ID de proyecto únicos para cada prueba. Tenga en cuenta que si decide hacer esto, deberá llamar
initializeTestEnvironment
como parte de cada prueba; Las reglas solo se cargan automáticamente para el ID de proyecto predeterminado. - Reestructura tus pruebas para que no interactúen con datos escritos previamente (por ejemplo, usa una colección diferente para cada prueba).
- Eliminar todos los datos escritos durante una prueba.
La configuración de la prueba es muy complicada.
Al configurar su prueba, es posible que desee modificar los datos de una manera que las reglas de seguridad de Cloud Firestore en realidad no lo permitan. Si sus reglas hacen que la configuración de la prueba sea compleja, intente usar RulesTestEnvironment.withSecurityRulesDisabled
en sus pasos de configuración, de modo que las lecturas y escrituras no generen errores PERMISSION_DENIED
.
Después de eso, su prueba puede realizar operaciones como usuario autenticado o no autenticado usando RulesTestEnvironment.authenticatedContext
y unauthenticatedContext
respectivamente. Esto le permite validar que sus reglas de seguridad de Cloud Firestore permitan/nieguen diferentes casos correctamente.