Firebase Realtime Database Emulator

The Realtime Database emulator is intended to make it easier to write unit tests that check the behavior of your database security rules.

In principle it may be possible to run your entire application against the local emulator instead of a production database, but there are a few issues that you might run into. In particular, the integration with Firebase Auth is broken. We're working on improving this story, but for now we'd encourage you to try out writing a few tests to make sure your security rules do what you expect.

When the emulator starts up, your database will be "locked down" from a security perspective (both ".read" and ".write" are false). Before writing, you'll have to set your security rules—you can do this directly from inside a unit testing framework using the testing SDK module, see below.

As always, feedback is greatly appreciated. Let us know what you think!

Differences between the emulator and production

  1. You do not have to explicitly create a database instance. The emulator will automatically create any database instance that is accessed.
  2. Each new database is started with closed rules, so non-admin users will not be able to read or write.
  3. Any database will accept the string "owner" as an admin auth token.
    1. If you want to use the REST api as an admin, include the header
      Authorization: Bearer owner.
    2. You can use this to set rules using curl. Assuming your rules are in a database.rules.json file, this should work:
      curl -X PUT -H 'Authorization: Bearer owner' --data @database.rules.json http://localhost:9000/.settings/rules.json?ns=<name>
  4. The database emulator does not have working interaction with other Firebase products. Notably, the normal Firebase auth flow will not work. Instead, we have provided the initializeTestApp() method in the testing module, which takes an auth field. The Firebase handle created using this method will behave as though it has successfully authenticated as whatever entity you provide. If you pass in null, it will behave as an unauthenticated user (auth != null rules will fail, for example).

Install the emulator

To install the Realtime Database emulator, use the Firebase CLI and follow the steps below.

  1. To install the Realtime Database emulator: firebase setup:emulators:database
  2. Start the emulator using the following command. The emulator runs during all your tests. firebase serve --only database

Interact with the emulator

A normal Firebase Realtime Database instance is accessible at a subdomain of firebaseio.com, and you can access the REST api like this:

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

The emulator runs locally, and is available at localhost:9000. To interact with a specific database instance, you will have to use a query parameter to specify the database name.

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

We've provided the @firebase/testing module to make it easier to interact with the emulator using the Firebase SDK. The @firebase/testing module allows you to interact with a locally running version of the Realtime Database emulator. If you get timeouts or ECONNREFUSED errors, double check that the emulator is running.

We strongly recommend using a recent version of Node.js to allow you to use async/await notation. Almost all of the behavior you might want to test involves asynchronous functions, and the testing module is designed to work with Promise-based code.

The module exposes the following methods:

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

Use this to create an app authenticated as a specific user to use in tests.

Returns an initialized firebase app corresponding to the database name and auth variable override specified in options. Note that this does NOT use databaseURL, as it is not running against a remote server.

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

initializeAdminApp({ databaseName: }) => FirebaseApp

Use this to create an app authenticated as an admin to set up state for tests.

Returns an initialized admin firebase app corresponding to the database name specified in options. This app bypasses security rules when reading and writing to the database.

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

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

Use this to set your database's rules.

Sends rules to a locally running database. Takes an options object that specifies your "databaseName" and your "rules" as strings.

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

apps() => [FirebaseApp]

Returns all the currently initialized test and admin apps.

Use this to clean up apps between or after tests (note that initialized apps with active listeners prevent JavaScript from exiting):

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

assertFails(pr: Promise) => Promise

Returns a promise that is rejected if the input succeeds and succeeds if the input is rejected.

Use this to assert that a database read or write fails:

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

assertSucceeds(pr: Promise) => Promise

Returns a promise that succeeds if the input succeeds and is rejected if the input is rejected.

Use this to assert that a database read or write succeeds:

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

Generate test reports

After running a suite of tests, you can access test coverage reports that show how each of your security rules was evaluated. To get the reports, query an exposed endpoint on the emulator while it's running. For a browser-friendly version, use the following URL:

http://localhost:9000/.inspect/coverage?ns=<database_name>

This breaks your rules into expressions and subexpressions that you can mouseover for more information, including number of executions and values returned. For the raw JSON version of this data, include the following URL in your query:

http://localhost:9000/.inspect/coverage.json?ns=<database_name>

Quickstart

If you just want to get a minimal example working, try the JavaScript quickstart.

Send feedback about...

Need help? Visit our support page.