Firebase Local Emulator Suite упрощает полную проверку функций и поведения вашего приложения. Это также отличный инструмент для проверки конфигураций Firebase Security Rules . Используйте эмуляторы Firebase для запуска и автоматизации модульных тестов в локальной среде. Методы, описанные в этом документе, должны помочь вам в создании и автоматизации модульных тестов для вашего приложения, которые проверяют ваши Rules .
Если вы еще этого не сделали, настройте эмуляторы Firebase .
Перед запуском эмулятора
Прежде чем начать использовать эмулятор, учтите следующее:
- Эмулятор изначально загрузит правила, указанные в поле
firestore.rulesилиstorage.rulesвашего файлаfirebase.json. Если файл не существует и вы не используете методloadFirestoreRulesилиloadStorageRules, как описано ниже, эмулятор будет рассматривать все проекты как имеющие открытые правила. - Хотя большинство SDK Firebase работают с эмуляторами напрямую, только библиотека
@firebase/rules-unit-testingподдерживает имитациюauthв правилах безопасности, что значительно упрощает модульное тестирование. Кроме того, библиотека поддерживает несколько специфических для эмуляторов функций, таких как очистка всех данных, как указано ниже. - Эмуляторы также будут принимать токены Firebase Auth, предоставленные через клиентские SDK, и соответствующим образом оценивать правила, что позволяет напрямую подключать ваше приложение к эмуляторам в интеграционных и ручных тестах.
Различия между эмуляторами баз данных и производственной средой.
- Нет необходимости явно создавать экземпляр базы данных. Эмулятор автоматически создаст любой экземпляр базы данных, к которому будет осуществлен доступ.
- Каждая новая база данных запускается с закрытыми правилами, поэтому пользователи, не являющиеся администраторами, не смогут читать или записывать данные.
- Каждая эмулируемая база данных применяет ограничения и квоты плана Spark (в частности, это ограничивает количество одновременных подключений к каждому экземпляру до 100).
- Любая база данных примет строку
"owner"в качестве токена авторизации администратора. - В настоящее время эмуляторы не имеют работающего взаимодействия с другими продуктами Firebase. В частности, обычный процесс аутентификации Firebase не работает. Вместо этого вы можете использовать метод
initializeTestApp()из библиотекиrules-unit-testing, который принимает поле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>
Запускайте локальные модульные тесты с помощью JavaScript SDK версии 9.
Firebase распространяет библиотеку модульного тестирования правил безопасности как с версией 9 JavaScript SDK, так и с версией 8 SDK. API библиотек существенно различаются. Мы рекомендуем библиотеку тестирования версии 9, которая более оптимизирована и требует меньше настроек для подключения к эмуляторам, что позволяет безопасно избежать случайного использования производственных ресурсов. Для обеспечения обратной совместимости мы продолжаем предоставлять библиотеку тестирования версии 8 .
- Общие методы тестирования и вспомогательные функции в SDK версии 9
- Специфические для эмулятора методы тестирования в SDK версии 9
Используйте модуль @firebase/rules-unit-testing для взаимодействия с локально запущенным эмулятором. Если вы получаете ошибки таймаута или ECONNREFUSED , убедитесь, что эмулятор действительно запущен.
Мы настоятельно рекомендуем использовать последнюю версию Node.js, чтобы вы могли использовать нотацию async/await . Практически все действия, которые вы, возможно, захотите протестировать, связаны с асинхронными функциями, и модуль тестирования разработан для работы с кодом, основанным на промисах.
Библиотека модульного тестирования v9 Rules всегда учитывает работу эмуляторов и никогда не затрагивает ваши производственные ресурсы.
Импорт библиотеки осуществляется с помощью модульных операторов импорта версии 9. Например:
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().doc('/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()
Запустите функцию настройки теста с контекстом, который ведет себя так, как если бы правила безопасности были отключены.
Этот метод принимает функцию обратного вызова, которая принимает контекст, обходящий правила безопасности, и возвращает промис. Контекст будет уничтожен после того, как промис разрешится/отклонится.
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 (модульной версии 9 или совместимой с версией 9).
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-адрес экземпляра базы данных реального времени. Если указан, возвращает экземпляр для эмулируемой версии пространства имен с параметрами, извлеченными из URL-адреса.
Cloud Storage
Cloud Storage
RulesTestEnvironment.clearStorage() => Promise<void>
Этот метод очищает объекты и метаданные в хранилищах, принадлежащих проекту projectId , настроенному для эмулятора Cloud Storage .
RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;
Этот метод возвращает экземпляр Storage, настроенный для подключения к эмулятору. Метод принимает URL-адрес gs:// к корзине Firebase Storage для тестирования. Если указан, возвращает экземпляр Storage для эмулируемой версии имени корзины.
Запускайте локальные модульные тесты с помощью JavaScript SDK v8.
Выберите продукт, чтобы увидеть методы, используемые Firebase Test SDK для взаимодействия с эмулятором.
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Этот метод возвращает инициализированное приложение 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
Этот метод возвращает промис, который отклоняется, если ввод успешен, или промис, который успешен, если ввод отклонен. Используйте его для проверки успешности операций чтения или записи в базу данных.
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") и правила ("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
Возвращает промис, который отклоняется, если входные данные успешны, и успешен, если входные данные отклонены.
Используйте это для подтверждения того, что операция чтения или записи в базу данных завершилась неудачей:
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 версии 8
Выберите продукт, чтобы увидеть методы, используемые Firebase Test SDK для взаимодействия с эмулятором.
Cloud Firestore
Cloud Firestore
initializeTestApp({ projectId: string, auth: Object }) => FirebaseApp
Этот метод возвращает инициализированное приложение 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
Этот метод возвращает промис, который отклоняется, если ввод успешен, или промис, который успешен, если ввод отклонен. Используйте его для проверки успешности операций чтения или записи в базу данных.
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") и правила ("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
Возвращает промис, который отклоняется, если входные данные успешны, и успешен, если входные данные отклонены.
Используйте это для подтверждения того, что операция чтения или записи в базу данных завершилась неудачей:
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());