Realtime Database エミュレータでセキュリティ ルールをテストする

Realtime Database エミュレータは、データベースのセキュリティ ルールの動作確認を行う単体テストを簡単に作成できるようにします。

エミュレータが起動すると、データベースはセキュリティの観点から「オープン」になります(すべての読み取りと書き込みが許可されます)。単体テスト フレームワークのセキュリティ ルールは、Firebase Test SDK モジュールを使用して変更できます(以下を参照)。

エミュレータと本番環境の違い

  1. データベース インスタンスを明示的に作成する必要がありません。エミュレータが、アクセスされるデータベース インスタンスを自動的に作成します。
  2. 新しいデータベースはオープンルールを使用して起動されるため、すべてのユーザーがすべてのパスの読み取りと書き込みを行うことができます。
  3. エミュレートされた各データベースには、Spark プランの制限と割り当てが適用されます(特に重要なのは、これにより各インスタンスの同時接続数が 100 に制限されることです)。
  4. どのデータベースも、文字列 "owner" を管理者認証トークンとして受け入れます。
    1. REST API を管理者として使用する場合は、以下のヘッダーを含めます。
      Authorization: Bearer owner
    2. このトークンは、curl を使用してルールを設定するのに使用できます。たとえば、ルールが database.rules.json ファイルにある場合は、以下のようになります。
      curl -X PUT -H 'Authorization: Bearer owner' --data @database.rules.json http://localhost:9000/.settings/rules.json?ns=<name>
  5. このデータベース エミュレータは、他の Firebase プロダクトと動的なやり取りを行いません。特に、通常の Firebase 認証フローは機能しません。その代わりに、Firebase Test SDK の中に auth フィールドを受け取る initializeTestApp() メソッドが用意されています。このメソッドを使用して作成された Firebase ハンドルは、どのようなエンティティを指定しても正常に認証されたかのように動作します。null を渡すと、認証されていないユーザーとして動作します(たとえば auth != null ルールは失敗します)。

エミュレータをインストールする

Realtime Database エミュレータをインストールするには、Firebase CLI を使用して以下のコマンドを実行します。

firebase setup:emulators:database

エミュレータを実行する

次のコマンドを使用してエミュレータを起動します。エミュレータは、プロセスを終了するまで実行されます。

firebase emulators:start --only database

Realtime Database エミュレータには Java 8 以上が必要です。

多くの場合、エミュレータを起動し、テストスイートを実行して、テストの実行後にエミュレータをシャットダウンします。これは emulators:exec コマンドで簡単に実施できます。

firebase emulators:exec --only database "./my-test-script.sh"

エミュレータが起動されると、デフォルト ポート(9000)での実行が試行されます。firebase.json ファイルの "emulators" セクションを修正することで、エミュレータ ポートを変更できます。

{
  // ...
  "emulators": {
    "database": {
      "port": "YOUR_PORT"
    }
  }
}

エミュレータとのやり取り

通常の Firebase Realtime Database インスタンスは、firebaseio.com のサブドメインからアクセスできるため、次の方法で REST API にアクセスできます。

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

エミュレータはローカルで実行され、localhost:9000 でアクセスできます。特定のデータベース インスタンスと対話するには、クエリ パラメータを使用してデータベース名を指定する必要があります。

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

Firebase SDK を使用したエミュレータとのやり取りを容易にするために、@firebase/testing モジュールを用意しています。@firebase/testing モジュールを使用すると、ローカルで実行中の Realtime Database エミュレータとやり取りできます。タイムアウトまたは ECONNREFUSED のエラーが発生する場合は、エミュレータが実行されていることを確認してください。

async/await の表記法を使用できるようにするため、新しいバージョンの Node.js を使用することを強くおすすめします。テスト対象となる可能性のある動作のほとんどには非同期関数があります。また、テスト モジュールは Promise ベースのコードで動作するように設計されています。

公開されているモジュールのメソッドは以下のとおりです。

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

このメソッドを使用すると、テストで使用するための、特定のユーザーとして認証されたアプリを作成できます。

オプションで指定されたデータベース名と auth 変数のオーバーライドに対応する、初期化された Firebase アプリを返します。リモート サーバーに対して実行されるものではないため、databaseURL を使用しない点に注意してください。

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

initializeAdminApp({ databaseName: }) => FirebaseApp

このメソッドを使用すると、テストの状態を設定するための、管理者として認証されたアプリを作成できます。

オプションで指定されたデータベース名に対応する初期化された Firebase 管理アプリを返します。このアプリは、データベースに対する読み書きを行う際にセキュリティ ルールを迂回します。

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

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

このメソッドを使用すると、データベースのルールを設定できます。

ローカルで実行されているデータベースにルールを送信します。データベースは、「databaseName」と「rules」を文字列で指定したオプション オブジェクトを受け取ります。

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

apps() => [FirebaseApp]

現在初期化されているテストと管理アプリをすべて返します。

このメソッドは、テスト中またはテスト後にアプリを消去するのに使用できます(アクティブなリスナーを持つ初期化されたアプリは JavaScript の終了を妨げるため、注意してください)。

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

assertFails(pr: Promise) => Promise

入力が成功した場合は拒否され、入力が拒否された場合は成功する Promise を返します。

このメソッドを以下のように使用して、データベースの読み取りまたは書き込みに失敗したことをアサートします。

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

assertSucceeds(pr: Promise) => Promise

入力が成功した場合は成功し、入力が拒否された場合は拒否される Promise を返します。

このメソッドを以下のように使用して、データベースの読み取りまたは書き込みが成功したことをアサートします。

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

テストレポートの生成

一連のテストを実行した後、それぞれのセキュリティ ルールの評価を示したテスト カバレッジ レポートにアクセスできます。レポートを取得するには、エミュレータの実行中に公開されたエンドポイントに対してクエリを実行します。ブラウザでの表示に適したバージョンを参照するには、次の URL を使用します。

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

これによりルールが式やサブ式に分割されます。それぞれの式の上にマウスカーソルを重ねて、実行回数や返された値などの詳細情報を確認できます。このデータの未加工の JSON バージョンを取得するには、クエリに次の URL を含めます。

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

クイックスタート

最小限のサンプルを動かしたい場合は、JavaScript のクイックスタートをお試しください。