Firebase Local Emulator Suite упрощает полную проверку функций и поведения вашего приложения. Это также отличный инструмент для проверки конфигураций Firebase Security Rules . Используйте Firebase Emulators для запуска и автоматизации модульных тестов в локальной среде. Методы, описанные в этом документе, должны помочь вам при создании и автоматизации модульных тестов для вашего приложения, которые проверяют ваши Rules .
Если вы еще этого не сделали, настройте эмуляторы Firebase .
Перед запуском эмулятора
Прежде чем начать использовать эмулятор, имейте в виду следующее:
- Эмулятор изначально загрузит правила, указанные в поле
firestore.rules
илиstorage.rules
вашего файлаfirebase.json
. Если файл не существует и вы не используете методloadFirestoreRules
илиloadStorageRules
, как описано ниже, эмулятор рассматривает все проекты как имеющие открытые правила. - Хотя большинство Firebase SDK работают с эмуляторами напрямую, только библиотека
@firebase/rules-unit-testing
поддерживает фиктивнуюauth
в правилах безопасности, что значительно упрощает модульные тесты. Кроме того, библиотека поддерживает несколько функций, специфичных для эмулятора, например очистку всех данных, как указано ниже. - Эмуляторы также будут принимать производственные токены Firebase Auth, предоставляемые через клиентские SDK, и соответствующим образом оценивать правила, что позволит подключать ваше приложение напрямую к эмуляторам при интеграционных и ручных тестах.
Различия между эмуляторами баз данных и производством
- Вам не нужно явно создавать экземпляр базы данных. Эмулятор автоматически создаст любой экземпляр базы данных, к которому осуществляется доступ.
- Каждая новая база данных запускается с закрытыми правилами, поэтому пользователи, не имеющие прав администратора, не смогут читать или писать.
- Каждая эмулируемая база данных применяет ограничения и квоты плана Spark (в частности, это ограничение каждого экземпляра 100 одновременными подключениями).
- Любая база данных примет строку
"owner"
в качестве токена аутентификации администратора. - В настоящее время эмуляторы не имеют рабочих взаимодействий с другими продуктами Firebase. В частности, обычный поток аутентификации Firebase не работает. Вместо этого вы можете использовать метод
initializeTestApp()
в библиотекеrules-unit-testing
, который принимает полеauth
. Объект Firebase, созданный с помощью этого метода, ведет себя так, как будто он успешно прошел аутентификацию как любая предоставленная вами сущность. Если вы передадитеnull
, он будет вести себя как неаутентифицированный пользователь (например, правилаauth != null
не пройдут).
Взаимодействие с эмулятором Realtime Database
Экземпляр Realtime Database доступен на поддомене firebaseio.com
, а доступ к API REST можно получить следующим образом:
https://<database_name>.firebaseio.com/path/to/my/data.json
Эмулятор работает локально и доступен по адресу localhost:9000
. Для взаимодействия с определенным экземпляром базы данных вам придется использовать параметр запроса ns
, чтобы указать имя базы данных.
http://localhost:9000/path/to/my/data.json?ns=<database_name>
Запуск локальных модульных тестов с помощью JavaScript SDK версии 9
Firebase распространяет библиотеку модульного тестирования Security Rules как с версией 9 JavaScript SDK, так и с версией 8 SDK. API библиотеки существенно различаются. Мы рекомендуем библиотеку тестирования v9, которая более оптимизирована и требует меньше настроек для подключения к эмуляторам, что позволяет безопасно избегать случайного использования производственных ресурсов. Для обратной совместимости мы продолжаем предоставлять библиотеку тестирования v8 .
- Общие методы тестирования и служебные функции в SDK v9
- Методы тестирования, специфичные для эмулятора, в SDK v9
Используйте модуль @firebase/rules-unit-testing
для взаимодействия с эмулятором, который работает локально. Если вы получаете тайм-ауты или ошибки ECONNREFUSED
, дважды проверьте, что эмулятор действительно запущен.
Мы настоятельно рекомендуем использовать последнюю версию Node.js, чтобы вы могли использовать нотацию async/await
. Почти все поведение, которое вы, возможно, захотите протестировать, включает асинхронные функции, а модуль тестирования предназначен для работы с кодом на основе Promise.
Библиотека модульного тестирования v9 Rules всегда знает об эмуляторах и никогда не затрагивает ваши производственные ресурсы.
Вы импортируете библиотеку с помощью операторов импорта v9 modular. Например:
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.
После импорта реализация модульных тестов включает в себя:
- Создание и настройка
RulesTestEnvironment
с помощью вызоваinitializeTestEnvironment
. - Настройка тестовых данных без запуска Rules с использованием удобного метода, который позволяет временно их обойти,
RulesTestEnvironment.withSecurityRulesDisabled
. - Настройка тестового набора и перехватов до/после для каждого теста с вызовами для очистки тестовых данных и среды, например
RulesTestEnvironment.cleanup()
илиRulesTestEnvironment.clearFirestore()
. - Реализация тестовых случаев, имитирующих состояния аутентификации, с использованием
RulesTestEnvironment.authenticatedContext
иRulesTestEnvironment.unauthenticatedContext
.
Общие методы и функции полезности
См. также методы тестирования, специфичные для эмуляторов, с использованием модульного API .
initializeTestEnvironment() => RulesTestEnvironment
Эта функция инициализирует тестовую среду для тестирования модулей правил. Сначала вызовите эту функцию для настройки теста. Для успешного выполнения требуется, чтобы были запущены эмуляторы.
Функция принимает необязательный объект, определяющий TestEnvironmentConfig
, который может состоять из идентификатора проекта и параметров конфигурации эмулятора.
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 и возвращает обещание. Контекст будет уничтожен, как только обещание будет разрешено/отклонено.
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 может использоваться с API клиентского SDK (модульный 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 может использоваться с API-интерфейсами клиентского SDK (модульными или с пространством имен, версии 9 или выше). Метод принимает URL-адрес экземпляра Realtime Database. Если указано, возвращает экземпляр для эмулированной версии пространства имен с параметрами, извлеченными из URL-адреса.
Cloud Storage
Cloud Storage
RulesTestEnvironment.clearStorage() => Promise<void>
Этот метод очищает объекты и метаданные в сегментах хранения, принадлежащих projectId
, настроенному для эмулятора Cloud Storage .
RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;
Этот метод возвращает экземпляр Storage, настроенный для подключения к эмулятору. Метод принимает URL-адрес gs://
к Firebase Storage Bucket для тестирования. Если указано, возвращает экземпляр Storage для эмулированной версии имени bucket.
Запуск локальных модульных тестов с помощью JavaScript SDK v8
Выберите продукт, чтобы увидеть методы, используемые Firebase Test SDK для взаимодействия с эмулятором.
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Этот метод возвращает инициализированное приложение Firebase, соответствующее идентификатору проекта и переменной auth, указанным в параметрах. Используйте это для создания приложения, аутентифицированного как определенный пользователь, для использования в тестах.
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
Этот метод возвращает обещание, которое отклоняется, если ввод успешен, или успешно, если ввод отклонен. Используйте это, чтобы утверждать, если чтение или запись в базу данных не удались.
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: 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
Используйте это для создания приложения, аутентифицированного как определенный пользователь, для использования в тестах.
Возвращает инициализированное приложение 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" и ваши "правила" как строки.
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
Возвращает обещание, которое отклоняется, если ввод успешен, и выполняется успешно, если ввод отклонен.
Используйте это, чтобы подтвердить, что чтение или запись в базу данных не удалась:
firebase.assertFails(app.database().ref("secret").once("value"));
assertSucceeds(pr: 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
Возвращает обещание, которое отклоняется, если ввод успешен, и выполняется успешно, если ввод отклонен.
Используйте это, чтобы подтвердить, что чтение или запись в контейнер хранилища завершились неудачей:
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
Возвращает обещание, которое выполняется, если ввод успешен, и отклоняется, если ввод отклонен.
Используйте это, чтобы подтвердить, что чтение или запись в контейнер хранилища выполнены успешно:
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());
API библиотеки RUT для JS SDK v8
Выберите продукт, чтобы увидеть методы, используемые Firebase Test SDK для взаимодействия с эмулятором.
Cloud Firestore
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Этот метод возвращает инициализированное приложение Firebase, соответствующее идентификатору проекта и переменной auth, указанным в параметрах. Используйте это для создания приложения, аутентифицированного как определенный пользователь, для использования в тестах.
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
Этот метод возвращает обещание, которое отклоняется, если ввод успешен, или успешно, если ввод отклонен. Используйте это, чтобы утверждать, если чтение или запись в базу данных не удались.
firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
assertSucceeds(pr: 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
Используйте это для создания приложения, аутентифицированного как определенный пользователь, для использования в тестах.
Возвращает инициализированное приложение 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" и ваши "правила" как строки.
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
Возвращает обещание, которое отклоняется, если ввод успешен, и выполняется успешно, если ввод отклонен.
Используйте это, чтобы подтвердить, что чтение или запись в базу данных не удалась:
firebase.assertFails(app.database().ref("secret").once("value"));
assertSucceeds(pr: 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
Возвращает обещание, которое отклоняется, если ввод успешен, и выполняется успешно, если ввод отклонен.
Используйте это, чтобы подтвердить, что чтение или запись в контейнер хранилища завершились неудачей:
firebase.assertFails(app.storage().ref("letters/private.doc").getMetadata());
assertSucceeds(pr: Promise) => Promise
Возвращает обещание, которое выполняется, если ввод успешен, и отклоняется, если ввод отклонен.
Используйте это, чтобы подтвердить, что чтение или запись в контейнер хранилища выполнены успешно:
firebase.assertFails(app.storage().ref("images/cat.png").getMetadata());