Firebase Local Emulator Suite を使用すると、アプリの機能と動作を簡単に検証できます。また、Firebase Local Emulator Suite は Firebase セキュリティ ルールの構成を確認するという点でも優れたツールです。Firebase エミュレータを使用して、ローカル環境で単体テストの実行と自動化を行います。アプリのセキュリティ ルールを検証する単体テストを作成して自動化する際は、このドキュメントで説明するメソッドが便利です。
まだ設定していない場合は、Firebase エミュレータを設定します。
エミュレータを実行する前に
エミュレータを使用する前に、次の点に注意してください。
- エミュレータは最初に、
firestore.rules
、またはfirebase.json
ファイルの 'storage.rules' フィールドで指定されたルールを読み込みます。ファイルが存在せず、次で説明するようにloadFirestoreRules
または 'loadStorageRules' メソッドを使用しない場合、エミュレータはすべてのプロジェクトをオープンルールが適用されるものとして扱います。 - ほとんどの Firebase SDK はエミュレータで直接動作しますが、セキュリティ ルールで
auth
の擬似的再現をサポートしているのは@firebase/rules-unit-testing
ライブラリのみです。したがって、このライブラリでは単体テストがはるかに簡単になります。また、このライブラリは以下にリストされているエミュレータ固有の機能(すべてのデータのクリアなど)もサポートしています。 - エミュレータは、クライアント SDK から提供される本番環境の Firebase Auth トークンも受け入れ、それに応じてルールを評価します。そのため、統合テストと手動テストでアプリケーションをエミュレータに直接接続できます。
データベース エミュレータと本番環境の違い
- データベース インスタンスを明示的に作成する必要がありません。エミュレータは、アクセス対象のデータベース インスタンスを自動的に作成します。
- 新しいデータベースはクローズド ルールを使用して起動されるため、管理者以外のユーザーが読み取りや書き込みを行うことはできません。
- エミュレートされた各データベースには、Spark プランの制限と割り当てが適用されます(特に重要なのは、これにより各インスタンスの同時接続数が 100 に制限されることです)。
- どのデータベースも、文字列
"owner"
を管理者認証トークンとして受け入れます。 - 現在のところ、エミュレータは他の Firebase プロダクトと機能するやり取りを行いません。特に、通常の Firebase Authentication フローは機能しません。代わりに、
rules-unit-testing
ライブラリのinitializeTestApp()
メソッドを使用できます。このメソッドはauth
フィールドを受け取ります。このメソッドを使用して作成された Firebase オブジェクトは、どのようなエンティティを指定しても正常に認証されたかのように動作します。null
を渡すと、認証されていないユーザーとして動作します(たとえばauth != null
ルールは失敗します)。
Realtime Database エミュレータを操作する
本番環境の Firebase Realtime Database インスタンスは、firebaseio.com
のサブドメインからアクセスできるため、次の方法で REST API にアクセスできます。
https://<database_name>.firebaseio.com/path/to/my/data.json
エミュレータはローカルで実行され、localhost:9000
でアクセスできます。特定のデータベース インスタンスと対話するには、クエリ パラメータの ns
を使用してデータベース名を指定する必要があります。
http://localhost:9000/path/to/my/data.json?ns=<database_name>
バージョン 9 の JavaScript SDK を使用してローカル単体テストを実行する
Firebase はセキュリティ ルールの単体テスト用ライブラリを配布しています。配布されているバージョンには、バージョン 9 の JavaScript SDK とバージョン 8 の SDK があります。これらのライブラリの API は大きく異なります。v9 テスト ライブラリの使用をおすすめします。v9 テスト ライブラリを使用すると、エミュレータへの接続がより効率化され、必要な設定も少なくて済みます。これにより、本番環境リソースが誤って使用されることを回避できます。下位互換性のために、引き続き v8 テスト ライブラリをご利用いただけます。
@firebase/rules-unit-testing
モジュールを使用して、ローカルで動作するエミュレータを操作します。タイムアウトまたは ECONNREFUSED
エラーが発生する場合は、エミュレータが実行されていることを確認してください。
async/await
の表記法を使用できるようにするため、新しいバージョンの Node.js を使用することを強くおすすめします。テスト対象となる可能性のある動作のほとんどには非同期関数があります。また、テスト モジュールは Promise ベースのコードで動作するように設計されています。
v9 ルールの単体テスト用ライブラリはエミュレータを常に認識し、本番環境のリソースに接続することはありません。
ライブラリをインポートするには、v9 モジュラー インポート ステートメントを使用します。次に例を示します。
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.
インポートしたら単体テストを実装します。実装には次の作業が含まれます。
initializeTestEnvironment
を呼び出して、RulesTestEnvironment
を作成して構成します。- ルールを一時的にバイパスできる便利なメソッド
RulesTestEnvironment.withSecurityRulesDisabled
を使用して、ルールをトリガーせずにテストデータをセットアップします。 RulesTestEnvironment.cleanup()
やRulesTestEnvironment.clearFirestore()
など、テストデータと環境をクリーンアップするための呼び出しを使用して、テストスイートとテストごとの前後のフックをセットアップします。RulesTestEnvironment.authenticatedContext
とRulesTestEnvironment.unauthenticatedContext
を使用して、認証状態を模倣するテストケースを実装します。
一般的なメソッドとユーティリティ関数
モジュール方式の API を使用したエミュレータ固有のテストメソッドもご覧ください。
initializeTestEnvironment() => RulesTestEnvironment
この関数は、ルールの単体テスト用の環境を初期化します。テストのセットアップを行うには、まずこの関数を呼び出します。これが正常に実行されるには、エミュレータが実行されている必要があります。
この関数は、TestEnvironmentConfig
を定義するオプションのオブジェクトを受け入れます。このオブジェクトはプロジェクト ID とエミュレータ構成設定で構成されます。
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
このメソッドは RulesTestContext
を作成します。これは、認証された Authentication ユーザーと同様に動作します。返されたコンテキストを介して作成されたリクエストには、疑似の Authentication トークンが添付されます。必要に応じて、Authentication トークン ペイロードのカスタムのクレームまたはオーバーライドを定義するオブジェクトを渡してください。
テストで返されたテスト コンテキスト オブジェクトを使用して、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
このメソッドは RulesTestContext
を作成します。これは、Authentication を介してログインしていないクライアントのように動作します。返されたコンテキストを介して作成されたリクエストには、Firebase Auth トークンが添付されません。
テストで返されたテスト コンテキスト オブジェクトを使用して、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()
セキュリティ ルールが無効になっているかのように動作するコンテキストで、テスト セットアップ関数を実行します。
このメソッドはコールバック関数を受け取ります。このコールバック関数は Security-Rules-bypassing コンテキストを受け取って Promise を返します。Promise が解決または拒否されると、コンテキストは破棄されます。
RulesTestEnvironment.cleanup()
このメソッドは、テスト環境で作成されたすべての RulesTestContexts
を破棄し、それらの元となっているリソースをクリーンアップします。これにより、クリーンな終了が可能になります。
このメソッドでは、エミュレータの状態は一切変更されません。複数のテストの合間にデータをリセットするには、アプリケーション エミュレータ固有のデータ消去メソッドを使用してください。
assertSucceeds(pr: Promise<any>)) => Promise<any>
これはテスト ケースのユーティリティ関数です。
この関数は、エミュレータ オペレーションをラップする指定された Promise が、セキュリティ ルール違反なしで解決されることをアサートします。
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
これはテスト ケースのユーティリティ関数です。
この関数は、エミュレータ オペレーションをラップする指定された Promise が、セキュリティ ルール違反により拒否されることをアサートします。
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
エミュレータ固有のメソッド
モジュール方式の API を使用した一般的なテストメソッドとユーティリティ関数もご覧ください。
Cloud Firestore
Cloud Firestore
RulesTestEnvironment.clearFirestore() => Promise<void>
このメソッドは、Firestore エミュレータ用に構成された projectId
に属する Firestore データベースのデータをクリアします。
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
このメソッドは、このテストのコンテキストの Firestore インスタンスを取得します。返された Firebase JS Client SDK インスタンスは、クライアント SDK API(v9 モジュラーまたは v9 互換)で使用できます。
Realtime Database
Realtime Database
RulesTestEnvironment.clearDatabase() => Promise<void>
このメソッドは、Realtime Database エミュレータ用に構成された projectId
に属する Realtime Database のデータをクリアします。
RulesTestContext.database(databaseURL?: Firestore.FirestoreSettings) => Firestore;
このテスト コンテキストの Realtime Database インスタンスを取得します。返された Firebase JS Client SDK インスタンスは、クライアント SDK API(バージョン 9 以降のモジュール方式の API または名前空間対応の API)で使用できます。このメソッドは、Realtime Database インスタンスの URL を受け取ります。この URL が指定されている場合は、この URL から抽出されたパラメータを使用して、エミュレートされた名前空間のバージョンのインスタンスを返します。
Cloud Storage
Cloud Storage
RulesTestEnvironment.clearStorage() => Promise<void>
このメソッドは、Cloud Storage エミュレータ用に構成された projectId
に属するストレージ バケットのオブジェクトとメタデータをクリアします。
RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;
このメソッドは、エミュレータに接続するように構成された Storage インスタンスを返します。このメソッドは、テストのために Firebase Storage バケットの gs://
URL を受け取ります。この URL が指定されている場合は、エミュレートされたバケット名のバージョンの Storage インスタンスを返します。
v8 JavaScript SDK を使用してローカル単体テストを実行する
プロダクトを選択すると、Firebase Test SDK によるエミュレータの操作に使用されるメソッドが表示されます。
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
このメソッドは、オプションで指定されたプロジェクト ID と auth 変数に対応する、初期化された Firebase アプリを返します。テストで使用するために、特定のユーザーとして認証されたアプリを作成するには、このメソッドを次のように使用します。
firebase.initializeTestApp({ projectId: "my-test-project", auth: { uid: "alice", email: "alice@example.com" } });
initializeAdminApp({ projectId: string }) => FirebaseApp
このメソッドは、初期化された管理者 Firebase アプリを返します。このアプリは、読み取りと書き込みを行う際にセキュリティ ルールを迂回します。テストの状態を設定するために、管理者として認証されたアプリを作成するには、このメソッドを次のように使用します。
firebase.initializeAdminApp({ projectId: "my-test-project" });
apps() => [FirebaseApp]
。このメソッドは、現在初期化されているテストと管理アプリをすべて返します。テスト間またはテスト後にアプリを消去するには、このメソッドを次のように使用します。
Promise.all(firebase.apps().map(app => app.delete()))
loadFirestoreRules({ projectId: string, rules: Object }) => Promise
このメソッドは、ローカルで実行されているデータベースにルールを送信し、ルールを文字列として指定するオブジェクトを取ります。データベースのルールを設定するには、このメソッドを次のように使用します。
firebase.loadFirestoreRules({ projectId: "my-test-project", rules: fs.readFileSync("/path/to/firestore.rules", "utf8") });
assertFails(pr: Promise) => Promise
このメソッドは、入力が成功した場合は拒否され、入力が拒否された場合は成功する Promise を返します。データベースの読み取りや書き込みが失敗したかどうかをアサートするには、このメソッドを次のように使用します。
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: Promise) => Promise
このメソッドは、入力が成功した場合は成功し、入力が拒否された場合は拒否される Promise を返します。データベースの読み取りや書き込みが成功したかどうかをアサートするには、このメソッドを次のように使用します。
firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
clearFirestoreData({ projectId: string }) => Promise
このメソッドは、ローカルで実行中の Firestore インスタンス内の特定のプロジェクトに関連付けられているすべてのデータを消去します。テスト後のクリーンアップには、このメソッドを次のように使用します。
firebase.clearFirestoreData({ projectId: "my-test-project" });
Realtime Database
Realtime Database
initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp
テストで使用するために、特定のユーザーとして認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたデータベース名と auth 変数のオーバーライドに対応する、初期化された Firebase アプリを返します。
firebase.initializeTestApp({
databaseName: "my-database",
auth: { uid: "alice" }
});
initializeAdminApp({ databaseName: string }) => FirebaseApp
テストの状態を設定するために、管理者として認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたデータベース名に対応する初期化された管理者 Firebase アプリを返します。このアプリは、データベースに対する読み書きを行う際にセキュリティ ルールを迂回します。
firebase.initializeAdminApp({ databaseName: "my-database" });
loadDatabaseRules({ databaseName: string, rules: Object }) => 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"));
Cloud Storage
Cloud Storage
initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp
テストで使用するために、特定のユーザーとして認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたストレージ バケット名と認証変数のオーバーライドに対応する、初期化された Firebase アプリを返します。
firebase.initializeTestApp({
storageBucket: "my-bucket",
auth: { uid: "alice" }
});
initializeAdminApp({ storageBucket: string }) => FirebaseApp
テストの状態を設定するために、管理者として認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたストレージ バケット名に対応する、初期化された管理 Firebase アプリを返します。このアプリは、バケットに対する読み書きを行う際にセキュリティ ルールを迂回します。
firebase.initializeAdminApp({ storageBucket: "my-bucket" });
loadStorageRules({ storageBucket: string, rules: Object }) => Promise
これを使用してストレージ バケットのルールを設定します。
ローカル管理のストレージ バケットにルールを送信します。"storageBucket" と "rules" を文字列として指定したオプション オブジェクトを取ります。
firebase
.loadStorageRules({
storageBucket: "my-bucket",
rules: fs.readFileSync("/path/to/storage.rules", "utf8")
});
apps() => [FirebaseApp]
現在初期化されているテストと管理アプリをすべて返します。
テスト間またはテスト後にアプリを消去するには、このメソッドを次のように使用します(初期化済みのアプリでアクティブなリスナーを持つ場合は、JavaScript を終了できないのでご注意ください)。
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
入力が成功した場合は拒否され、入力が拒否された場合は成功する Promise を返します。
これを使用して、ストレージ バケットの読み取りまたは書き込みに失敗したことをアサートします。
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
入力が成功した場合は成功し、入力が拒否された場合は拒否される Promise を返します。
これを使用して、ストレージ バケットの読み取りまたは書き込みが成功したことをアサートします。
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());
JS SDK v8 用の RUT ライブラリ API
プロダクトを選択すると、Firebase Test SDK によるエミュレータの操作に使用されるメソッドが表示されます。
Cloud Firestore
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
このメソッドは、オプションで指定されたプロジェクト ID と auth 変数に対応する、初期化された Firebase アプリを返します。テストで使用するために、特定のユーザーとして認証されたアプリを作成するには、このメソッドを次のように使用します。
firebase.initializeTestApp({ projectId: "my-test-project", auth: { uid: "alice", email: "alice@example.com" } });
initializeAdminApp({ projectId: string }) => FirebaseApp
このメソッドは、初期化された管理者 Firebase アプリを返します。このアプリは、読み取りと書き込みを行う際にセキュリティ ルールを迂回します。テストの状態を設定するために、管理者として認証されたアプリを作成するには、このメソッドを次のように使用します。
firebase.initializeAdminApp({ projectId: "my-test-project" });
apps() => [FirebaseApp]
。このメソッドは、現在初期化されているテストと管理アプリをすべて返します。テスト間またはテスト後にアプリを消去するには、このメソッドを次のように使用します。
Promise.all(firebase.apps().map(app => app.delete()))
loadFirestoreRules({ projectId: string, rules: Object }) => Promise
このメソッドは、ローカルで実行されているデータベースにルールを送信し、ルールを文字列として指定するオブジェクトを取ります。データベースのルールを設定するには、このメソッドを次のように使用します。
firebase.loadFirestoreRules({ projectId: "my-test-project", rules: fs.readFileSync("/path/to/firestore.rules", "utf8") });
assertFails(pr: Promise) => Promise
このメソッドは、入力が成功した場合は拒否され、入力が拒否された場合は成功する Promise を返します。データベースの読み取りや書き込みが失敗したかどうかをアサートするには、このメソッドを次のように使用します。
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: Promise) => Promise
このメソッドは、入力が成功した場合は成功し、入力が拒否された場合は拒否される Promise を返します。データベースの読み取りや書き込みが成功したかどうかをアサートするには、このメソッドを次のように使用します。
firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
clearFirestoreData({ projectId: string }) => Promise
このメソッドは、ローカルで実行中の Firestore インスタンス内の特定のプロジェクトに関連付けられているすべてのデータを消去します。テスト後のクリーンアップには、このメソッドを次のように使用します。
firebase.clearFirestoreData({ projectId: "my-test-project" });
Realtime Database
Realtime Database
initializeTestApp({ databaseName: string, auth: Object }) => FirebaseApp
テストで使用するために、特定のユーザーとして認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたデータベース名と auth 変数のオーバーライドに対応する、初期化された Firebase アプリを返します。
firebase.initializeTestApp({
databaseName: "my-database",
auth: { uid: "alice" }
});
initializeAdminApp({ databaseName: string }) => FirebaseApp
テストの状態を設定するために、管理者として認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたデータベース名に対応する初期化された管理者 Firebase アプリを返します。このアプリは、データベースに対する読み書きを行う際にセキュリティ ルールを迂回します。
firebase.initializeAdminApp({ databaseName: "my-database" });
loadDatabaseRules({ databaseName: string, rules: Object }) => 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"));
Cloud Storage
Cloud Storage
initializeTestApp({ storageBucket: string, auth: Object }) => FirebaseApp
テストで使用するために、特定のユーザーとして認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたストレージ バケット名と認証変数のオーバーライドに対応する、初期化された Firebase アプリを返します。
firebase.initializeTestApp({
storageBucket: "my-bucket",
auth: { uid: "alice" }
});
initializeAdminApp({ storageBucket: string }) => FirebaseApp
テストの状態を設定するために、管理者として認証されたアプリを作成するには、このメソッドを次のように使用します。
オプションで指定されたストレージ バケット名に対応する、初期化された管理 Firebase アプリを返します。このアプリは、バケットに対する読み書きを行う際にセキュリティ ルールを迂回します。
firebase.initializeAdminApp({ storageBucket: "my-bucket" });
loadStorageRules({ storageBucket: string, rules: Object }) => Promise
これを使用してストレージ バケットのルールを設定します。
ローカル管理のストレージ バケットにルールを送信します。"storageBucket" と "rules" を文字列として指定したオプション オブジェクトを取ります。
firebase
.loadStorageRules({
storageBucket: "my-bucket",
rules: fs.readFileSync("/path/to/storage.rules", "utf8")
});
apps() => [FirebaseApp]
現在初期化されているテストと管理アプリをすべて返します。
テスト間またはテスト後にアプリを消去するには、このメソッドを次のように使用します(初期化済みのアプリでアクティブなリスナーを持つ場合は、JavaScript を終了できないのでご注意ください)。
Promise.all(firebase.apps().map(app => app.delete()))
assertFails(pr: Promise) => Promise
入力が成功した場合は拒否され、入力が拒否された場合は成功する Promise を返します。
これを使用して、ストレージ バケットの読み取りまたは書き込みに失敗したことをアサートします。
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
入力が成功した場合は成功し、入力が拒否された場合は拒否される Promise を返します。
これを使用して、ストレージ バケットの読み取りまたは書き込みが成功したことをアサートします。
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());