Firebase Local Emulator Suite упрощает полную проверку функций и поведения вашего приложения. Он также является отличным инструментом для проверки конфигураций Firebase Security Rules . Используйте эмуляторы Firebase для запуска и автоматизации модульных тестов в локальной среде. Методы, описанные в этом документе, помогут вам в создании и автоматизации модульных тестов для проверки 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
, и вы можете получить доступ к 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 распространяет библиотеку модульного тестирования Security Rules как с JavaScript SDK версии 9, так и с SDK версии 8. API библиотек существенно различаются. Мы рекомендуем библиотеку тестирования версии 9, которая более оптимизирована и требует меньше настроек для подключения к эмуляторам, что позволяет избежать случайного использования ресурсов производства. Для обеспечения обратной совместимости мы по-прежнему предоставляем библиотеку тестирования версии 8 .
- Распространенные методы тестирования и служебные функции в SDK v9
- Методы тестирования, специфичные для эмулятора, в SDK v9
Используйте модуль @firebase/rules-unit-testing
для взаимодействия с эмулятором, работающим локально. Если возникают тайм-ауты или ошибки ECONNREFUSED
, ещё раз проверьте, запущен ли эмулятор.
Мы настоятельно рекомендуем использовать последнюю версию Node.js, чтобы вы могли использовать нотацию async/await
. Практически всё поведение, которое вы хотите протестировать, включает асинхронные функции, и модуль тестирования разработан для работы с кодом на основе Promise.
Библиотека модульного тестирования правил v9 всегда знает об эмуляторах и никогда не трогает ваши производственные ресурсы.
Библиотека импортируется с помощью операторов модульного импорта версии 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(), '/users/alice'), { ... });
RulesTestEnvironment.unauthenticatedContext() => RulesTestContext
Этот метод создаёт RulesTestContext
, который ведёт себя как клиент, не прошедший Authentication . К запросам, созданным через возвращаемый контекст, не будут прикреплены токены аутентификации Firebase.
Используйте возвращенный объект контекста теста в своих тестах для доступа к любым настроенным экземплярам эмулятора, включая настроенные с помощью 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 (модульным или совместимым с 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;
Этот метод возвращает экземпляр хранилища, настроенный для подключения к эмулятору. Метод принимает URL-адрес gs://
к Firebase Storage Bucket для тестирования. Если указано, возвращает экземпляр хранилища для эмулированной версии имени контейнера.
Запускайте локальные модульные тесты с помощью 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 v8
Выберите продукт, чтобы увидеть методы, используемые 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());