O Pacote de emuladores locais do Firebase facilita a validação completa dos recursos e comportamento do app. Também é uma ótima ferramenta para verificar as configurações das regras de segurança do Firebase. Use os emuladores do Firebase para executar e automatizar testes de unidade em um ambiente local. Os métodos descritos neste documento vão ajudar você a criar e automatizar testes de unidade que validem suas regras do app.
Configure os emuladores do Firebase caso ainda não tenha feito isso.
Antes de executar o emulador
Considere as seguintes informações antes de começar a usar o emulador:
- Inicialmente, o emulador carregará as regras especificadas no campo
firestore.rules
ou "storage.rules" do seu arquivofirebase.json
. Se o arquivo não existir e você não usar o métodoloadFirestoreRules
ou "loadStorageRules", conforme descrito abaixo, o emulador tratará todos os projetos como tendo regras abertas. - Enquanto
a maioria dos SDKs do Firebase
funcionam com emuladores diretamente, somente a biblioteca
@firebase/rules-unit-testing
tem suporte à simulação deauth
nas regras de segurança, o que facilita muito os testes de unidade. Além disso, a biblioteca tem suporte a alguns recursos específicos de emulador, como limpar todos os dados, conforme listado abaixo. - Os emuladores também aceitarão tokens de produção do Firebase Authentication, fornecidos pelos SDKs clientes e avaliarão as regras, o que permite conectar o aplicativo diretamente aos emuladores em testes manuais e de integração.
Diferenças entre os emuladores de banco de dados e a produção
- Você não precisa criar uma instância de banco de dados de maneira explícita. O emulador criará automaticamente qualquer instância como essa que for acessada.
- Cada novo banco de dados é iniciado com regras fechadas. Dessa forma, usuários que não forem administradores não terão permissão para realizar operações de leitura ou gravação.
- Cada banco de dados emulado aplica os limites e as cotas do plano Spark (observe que isso limita cada instância a 100 conexões simultâneas).
- Qualquer banco de dados aceitará a string
"owner"
como um token de autenticação de administrador. - No momento, os emuladores não têm interações de trabalho com outros produtos do Firebase. Além disso, é importante ressaltar que o Firebase Authentication não funcionará no fluxo normal.
Em vez disso, é possível usar o método
initializeTestApp()
na bibliotecarules-unit-testing
, que usa um campoauth
. O objeto do Firebase criado por meio desse método se comportará como se tivesse sido autenticado com sucesso como qualquer entidade que você fornecer. Casonull
seja transmitido, ele se comportará como um usuário não autenticado. Por exemplo, as regrasauth != null
falharão.
Como interagir com o emulador do Realtime Database
É possível acessar uma instância de produção do Firebase Realtime Database usando um subdomínio de firebaseio.com
. Acesse a API REST usando o seguinte comando:
https://<database_name>.firebaseio.com/path/to/my/data.json
O emulador é executado localmente e está disponível em localhost:9000
. Para interagir
com uma instância de banco de dados específica, você precisará usar um parâmetro de consulta ns
a fim de especificar o nome desse banco de dados.
http://localhost:9000/path/to/my/data.json?ns=<database_name>
Executar testes de unidade locais com o SDK para JavaScript versão 9
O Firebase distribui uma biblioteca de testes de unidade de regras de segurança com o SDK para JavaScript versão 9 e 8. As APIs da biblioteca são significativamente diferentes. Recomendamos a biblioteca de testes v9, que é mais simples e requer menos configuração para se conectar a emuladores e, portanto, evita o uso acidental de recursos de produção. Para oferecer compatibilidade com versões anteriores, continuamos a disponibilizar a biblioteca de testes v8.
- Métodos de teste comuns e funções utilitárias no SDK v9
- Métodos de teste específicos do emulador no SDK v9
Use o módulo @firebase/rules-unit-testing
para interagir com o emulador
executado localmente. Se você alcançar o tempo limite ou receber erros ECONNREFUSED
, verifique
se o emulador está sendo executado.
Recomendamos o uso de uma versão recente do Node.js para que você possa usar a
notação async/await
. Quase todo o comportamento que pode ser testado
envolve funções assíncronas, e o módulo de teste é projetado para funcionar
com código baseado em promessas.
A biblioteca de teste de unidade de regras v9 está sempre ciente dos emuladores e nunca interfere nos recursos de produção.
A biblioteca é importada usando instruções de importação modular v9. Exemplo:
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.
Depois de importados, a implementação de testes de unidade envolve:
- a criação e a configuração de um
RulesTestEnvironment
com uma chamada parainitializeTestEnvironment
; - a configuração de dados de teste sem acionar regras, usando um método de
conveniência que permite ignorá-las temporariamente,
RulesTestEnvironment.withSecurityRulesDisabled
; - a configuração do conjunto de testes e os hooks por teste antes/depois com as chamadas para
limpar os dados e o ambiente de teste, como
RulesTestEnvironment.cleanup()
ouRulesTestEnvironment.clearFirestore()
; - a implementação de casos de teste que imitam estados de autenticação usando
RulesTestEnvironment.authenticatedContext
eRulesTestEnvironment.unauthenticatedContext
.
Métodos comuns e funções utilitárias
Consulte também métodos de teste específicos do emulador usando a API modular.
initializeTestEnvironment() => RulesTestEnvironment
Essa função inicializa um ambiente de teste para testes de unidade de regras. Chame essa função primeiro para configurar o teste. A execução bem-sucedida requer que os emuladores estejam em execução.
A função aceita um objeto opcional que define um TestEnvironmentConfig
,
que pode consistir em um ID do projeto e em configurações do emulador.
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
Esse método cria um RulesTestContext
, que se comporta como um usuário autenticado
do Authentication. As solicitações criadas pelo contexto retornado terão um token
simulado do Authentication anexados. Opcionalmente, transmita um objeto que define declarações personalizadas ou
substituições para payloads de tokens do Authentication.
Use o objeto de contexto de teste retornado nos testes para acessar qualquer instância
configurada do emulador, incluindo as configuradas com 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
Esse método cria um RulesTestContext
, que se comporta como um cliente não
conectado pelo Authentication. As solicitações criadas pelo contexto retornado não
terão tokens do Firebase Auth anexados.
Use o objeto de contexto de teste retornado nos testes para acessar qualquer instância
configurada do emulador, incluindo as configuradas com 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()
Execute uma função de configuração de teste com um contexto que se comporte como se as regras de segurança estivessem desativadas.
Esse método usa uma função de callback com um contexto que ignora as regras de segurança e retorna uma promessa. O contexto será destruído quando a promessa for resolvida ou rejeitada.
RulesTestEnvironment.cleanup()
Esse método destrói todos os RulesTestContexts
criados no ambiente de teste e
limpa os recursos restantes, permitindo uma saída limpa.
Esse método não altera o estado dos emuladores. Para redefinir dados entre testes, use o método do aplicativo de dados limpos específico para emulador.
assertSucceeds(pr: Promise<any>)) => Promise<any>
Esta é uma função utilitária do caso de teste.
A função declara que a promessa fornecida que envolve uma operação de emulador será resolvida sem violações das regras de segurança.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
Esta é uma função utilitária do caso de teste.
A função declara que a promessa fornecida que envolve uma operação de emulador será rejeitada com uma violação das regras de segurança.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
Métodos específicos para emulador
Confira também métodos de teste comuns e funções utilitárias usando a API modular.
Cloud Firestore
Cloud Firestore
RulesTestEnvironment.clearFirestore() => Promise<void>
Esse método limpa dados no banco de dados do Firestore que pertence ao
projectId
configurado para o emulador do Firestore.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
Esse método recebe uma instância do Firestore para este contexto de teste. A instância retornada do SDK cliente do Firebase para JS pode ser usada com as APIs do SDK cliente (v9 modular ou v9 compatível).
Realtime Database
Realtime Database
RulesTestEnvironment.clearDatabase() => Promise<void>
Esse método limpa os dados no Realtime Database que pertencem ao
projectId
configurado para o emulador do Realtime Database.
RulesTestContext.database(databaseURL?: Firestore.FirestoreSettings) => Firestore;
Consiga uma instância do Realtime Database para este contexto de teste. A instância retornada do SDK do cliente do Firebase para JavaScript pode ser usada com as APIs do SDK do cliente (modular ou namespace, versão 9 ou posterior). O método aceita um URL da instância do Realtime Database. Se especificado, retorna uma instância de uma versão emulada do namespace com parâmetros extraídos do URL.
Cloud Storage
Cloud Storage
RulesTestEnvironment.clearStorage() => Promise<void>
Esse método limpa objetos e metadados em buckets de armazenamento pertencentes ao
projectId
configurado para o emulador do Cloud Storage.
RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;
Esse método retorna uma instância do Storage configurada para se conectar ao emulador.
O método aceita um URL gs://
para o bucket do Firebase Storage para testes. Se especificado, retorna uma instância do Storage para uma versão emulada do nome do bucket.
Executar testes de unidade locais com o SDK para JavaScript v8
Selecione um produto para ver os métodos usados pelo SDK de teste do Firebase a fim de interagir com o emulador.
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Esse método retorna um aplicativo do Firebase inicializado que corresponde ao ID do projeto e à variável de autenticação especificados nas opções. Use esse método e crie um app autenticado como um usuário específico para ser utilizado em testes.
firebase.initializeTestApp({ projectId: "my-test-project", auth: { uid: "alice", email: "alice@example.com" } });
initializeAdminApp({ projectId: string }) => FirebaseApp
Esse método retorna um aplicativo de administrador inicializado do Firebase. As regras de segurança são ignoradas quando esse aplicativo executa leituras e gravações. Use-o para criar um app autenticado como administrador e definir o estado para os testes.
firebase.initializeAdminApp({ projectId: "my-test-project" });
apps() => [FirebaseApp]
Esse método retorna todos os apps de teste e administração inicializados e em execução no momento.
Ele pode ser usado para limpar aplicativos entre ou após os testes.
Promise.all(firebase.apps().map(app => app.delete()))
loadFirestoreRules({ projectId: string, rules: Object }) => Promise
Esse método envia regras para um banco de dados em execução localmente. Ele utiliza um objeto que especifica as regras como uma string. Use-o para definir as regras do seu banco de dados.
firebase.loadFirestoreRules({ projectId: "my-test-project", rules: fs.readFileSync("/path/to/firestore.rules", "utf8") });
assertFails(pr: Promise) => Promise
Esse método retorna uma promessa que será recusada se a entrada for concluída e que será concluída se a entrada for recusada. Use-o para informar se ocorreu uma falha na leitura ou gravação no banco de dados.
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: Promise) => Promise
Esse método retorna uma promessa que será concluída se a entrada for concluída e que será recusada se a entrada for recusada. Use-o para informar se uma leitura ou gravação no banco de dados foi concluída.
firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
clearFirestoreData({ projectId: string }) => Promise
Esse método limpa todos os dados associados a um projeto específico na instância do Firestore que estão em execução localmente. Use-o para limpar os dados após os testes.
firebase.clearFirestoreData({ projectId: "my-test-project" });
Realtime Database
Realtime Database
initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp
Use esse método para criar um aplicativo autenticado como um usuário específico a ser utilizado em testes.
Ele retorna um aplicativo do Firebase inicializado correspondente ao nome do banco de dados e à modificação da variável de autenticação especificada nas opções.
firebase.initializeTestApp({
databaseName: "my-database",
auth: { uid: "alice" }
});
initializeAdminApp({ databaseName: string }) => FirebaseApp
Use esse método para criar um app autenticado como administrador e configurar o estado para os testes.
Ele retorna um aplicativo de administrador do Firebase inicializado correspondente ao nome do banco de dados especificado nas opções. Esse aplicativo ignora as regras de segurança durante a leitura e a gravação no banco de dados.
firebase.initializeAdminApp({ databaseName: "my-database" });
loadDatabaseRules({ databaseName: string, rules: Object }) => Promise
Use esse método para definir as regras do seu banco de dados.
Ele envia regras para um banco de dados executado localmente. Além disso, ele usa um objeto de opções que especifica "databaseName" e "rules" como strings.
firebase
.loadDatabaseRules({
databaseName: "my-database",
rules: "{'rules': {'.read': false, '.write': false}}"
});
apps() => [FirebaseApp]
Esse método retorna todos os aplicativos de teste e de administrador inicializados no momento.
Use-o para limpar aplicativos durante e depois dos testes. Observação: os aplicativos inicializados com listeners ativos impedem o JavaScript de finalizar a execução:
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Esse método retorna uma promessa que será recusada se a entrada for concluída e que será concluída se a entrada for recusada.
Use-o para informar que ocorreu uma falha na leitura ou na gravação no banco de dados:
firebase.assertFails(app.database().ref("secret").once("value"));
assertSucceeds(pr: Promise) => Promise
Esse método retorna uma promessa que será concluída se a entrada for concluída e será recusada se a entrada for recusada.
Use-o para informar que uma leitura ou gravação no banco de dados foi concluída:
firebase.assertSucceeds(app.database().ref("public").once("value"));
Cloud Storage
Cloud Storage
initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp
Use esse método para criar um aplicativo autenticado como um usuário específico a ser utilizado em testes.
Retorna um app do Firebase inicializado correspondente ao nome do bucket de armazenamento e à substituição da variável de autenticação especificada nas opções.
firebase.initializeTestApp({
storageBucket: "my-bucket",
auth: { uid: "alice" }
});
initializeAdminApp({ storageBucket: string }) => FirebaseApp
Use esse método para criar um app autenticado como administrador e configurar o estado para os testes.
Retorna um app do Firebase de administrador inicializado que corresponde ao nome do bucket de armazenamento especificado nas opções. Esse aplicativo ignora as regras de segurança durante a leitura e a gravação no bucket.
firebase.initializeAdminApp({ storageBucket: "my-bucket" });
loadStorageRules({ storageBucket: string, rules: Object }) => Promise
Use-o para definir as regras do bucket de armazenamento.
Envia regras para buckets de armazenamento gerenciados localmente. Além disso, ele usa um objeto de opções que especifica "storageBucket" e "rules" como strings.
firebase
.loadStorageRules({
storageBucket: "my-bucket",
rules: fs.readFileSync("/path/to/storage.rules", "utf8")
});
apps() => [FirebaseApp]
Esse método retorna todos os aplicativos de teste e de administrador inicializados no momento.
Use-o para limpar aplicativos durante e depois dos testes. Observação: os aplicativos inicializados com listeners ativos impedem o JavaScript de finalizar a execução:
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Esse método retorna uma promessa que será recusada se a entrada for concluída e que será concluída se a entrada for recusada.
Use-o para informar se ocorreu uma falha na leitura ou gravação no bucket de armazenamento:
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
Esse método retorna uma promessa que será concluída se a entrada for concluída e será recusada se a entrada for recusada.
Use-o para informar a conclusão de uma leitura ou gravação no bucket de armazenamento:
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());
API RUT Library para o SDK JS v8
Selecione um produto para ver os métodos usados pelo SDK de teste do Firebase a fim de interagir com o emulador.
Cloud Firestore
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Esse método retorna um aplicativo do Firebase inicializado que corresponde ao ID do projeto e à variável de autenticação especificados nas opções. Use esse método e crie um app autenticado como um usuário específico para ser utilizado em testes.
firebase.initializeTestApp({ projectId: "my-test-project", auth: { uid: "alice", email: "alice@example.com" } });
initializeAdminApp({ projectId: string }) => FirebaseApp
Esse método retorna um aplicativo de administrador inicializado do Firebase. As regras de segurança são ignoradas quando esse aplicativo executa leituras e gravações. Use-o para criar um app autenticado como administrador e definir o estado para os testes.
firebase.initializeAdminApp({ projectId: "my-test-project" });
apps() => [FirebaseApp]
Esse método retorna todos os apps de teste e administração inicializados e em execução no momento.
Ele pode ser usado para limpar aplicativos entre ou após os testes.
Promise.all(firebase.apps().map(app => app.delete()))
loadFirestoreRules({ projectId: string, rules: Object }) => Promise
Esse método envia regras para um banco de dados em execução localmente. Ele utiliza um objeto que especifica as regras como uma string. Use-o para definir as regras do seu banco de dados.
firebase.loadFirestoreRules({ projectId: "my-test-project", rules: fs.readFileSync("/path/to/firestore.rules", "utf8") });
assertFails(pr: Promise) => Promise
Esse método retorna uma promessa que será recusada se a entrada for concluída e que será concluída se a entrada for recusada. Use-o para informar se ocorreu uma falha na leitura ou gravação no banco de dados.
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: Promise) => Promise
Esse método retorna uma promessa que será concluída se a entrada for concluída e que será recusada se a entrada for recusada. Use-o para informar se uma leitura ou gravação no banco de dados foi concluída.
firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
clearFirestoreData({ projectId: string }) => Promise
Esse método limpa todos os dados associados a um projeto específico na instância do Firestore que estão em execução localmente. Use-o para limpar os dados após os testes.
firebase.clearFirestoreData({ projectId: "my-test-project" });
Realtime Database
Realtime Database
initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp
Use esse método para criar um aplicativo autenticado como um usuário específico a ser utilizado em testes.
Ele retorna um aplicativo do Firebase inicializado correspondente ao nome do banco de dados e à modificação da variável de autenticação especificada nas opções.
firebase.initializeTestApp({
databaseName: "my-database",
auth: { uid: "alice" }
});
initializeAdminApp({ databaseName: string }) => FirebaseApp
Use esse método para criar um app autenticado como administrador e configurar o estado para os testes.
Ele retorna um aplicativo de administrador do Firebase inicializado correspondente ao nome do banco de dados especificado nas opções. Esse aplicativo ignora as regras de segurança durante a leitura e a gravação no banco de dados.
firebase.initializeAdminApp({ databaseName: "my-database" });
loadDatabaseRules({ databaseName: string, rules: Object }) => Promise
Use esse método para definir as regras do seu banco de dados.
Ele envia regras para um banco de dados executado localmente. Além disso, ele usa um objeto de opções que especifica "databaseName" e "rules" como strings.
firebase
.loadDatabaseRules({
databaseName: "my-database",
rules: "{'rules': {'.read': false, '.write': false}}"
});
apps() => [FirebaseApp]
Esse método retorna todos os aplicativos de teste e de administrador inicializados no momento.
Use-o para limpar aplicativos durante e depois dos testes. Observação: os aplicativos inicializados com listeners ativos impedem o JavaScript de finalizar a execução:
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Esse método retorna uma promessa que será recusada se a entrada for concluída e que será concluída se a entrada for recusada.
Use-o para informar que ocorreu uma falha na leitura ou na gravação no banco de dados:
firebase.assertFails(app.database().ref("secret").once("value"));
assertSucceeds(pr: Promise) => Promise
Esse método retorna uma promessa que será concluída se a entrada for concluída e será recusada se a entrada for recusada.
Use-o para informar que uma leitura ou gravação no banco de dados foi concluída:
firebase.assertSucceeds(app.database().ref("public").once("value"));
Cloud Storage
Cloud Storage
initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp
Use esse método para criar um aplicativo autenticado como um usuário específico a ser utilizado em testes.
Retorna um app do Firebase inicializado correspondente ao nome do bucket de armazenamento e à substituição da variável de autenticação especificada nas opções.
firebase.initializeTestApp({
storageBucket: "my-bucket",
auth: { uid: "alice" }
});
initializeAdminApp({ storageBucket: string }) => FirebaseApp
Use esse método para criar um app autenticado como administrador e configurar o estado para os testes.
Retorna um app do Firebase de administrador inicializado que corresponde ao nome do bucket de armazenamento especificado nas opções. Esse aplicativo ignora as regras de segurança durante a leitura e a gravação no bucket.
firebase.initializeAdminApp({ storageBucket: "my-bucket" });
loadStorageRules({ storageBucket: string, rules: Object }) => Promise
Use-o para definir as regras do bucket de armazenamento.
Envia regras para buckets de armazenamento gerenciados localmente. Além disso, ele usa um objeto de opções que especifica "storageBucket" e "rules" como strings.
firebase
.loadStorageRules({
storageBucket: "my-bucket",
rules: fs.readFileSync("/path/to/storage.rules", "utf8")
});
apps() => [FirebaseApp]
Esse método retorna todos os aplicativos de teste e de administrador inicializados no momento.
Use-o para limpar aplicativos durante e depois dos testes. Observação: os aplicativos inicializados com listeners ativos impedem o JavaScript de finalizar a execução:
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
Esse método retorna uma promessa que será recusada se a entrada for concluída e que será concluída se a entrada for recusada.
Use-o para informar se ocorreu uma falha na leitura ou gravação no bucket de armazenamento:
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
Esse método retorna uma promessa que será concluída se a entrada for concluída e será recusada se a entrada for recusada.
Use-o para informar a conclusão de uma leitura ou gravação no bucket de armazenamento:
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());