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
Экземпляр рабочей 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 распространяет библиотеку модульного тестирования правил безопасности как с SDK JavaScript версии 9, так и с SDK версии 8. API библиотеки существенно отличаются. Мы рекомендуем библиотеку тестирования v9, которая более оптимизирована и требует меньше настроек для подключения к эмуляторам и, таким образом, позволяет безопасно избежать случайного использования производственных ресурсов. В целях обратной совместимости мы продолжаем делать доступной библиотеку тестирования v8 .
- Общие методы тестирования и служебные функции в SDK версии 9.
- Методы тестирования, специфичные для эмулятора, в v9 SDK
Используйте модуль @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>
Это служебная функция тестового примера.
Функция утверждает, что предоставленное обещание, обертывающее операцию эмулятора, будет разрешено без нарушений правил безопасности.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
Это служебная функция тестового примера.
Функция утверждает, что предоставленное обещание, обертывающее операцию эмулятора, будет отклонено с нарушением правил безопасности.
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-адрес экземпляра базы данных реального времени. Если указано, возвращает экземпляр эмулируемой версии пространства имен с параметрами, извлеченными из URL-адреса.
Cloud Storage
Cloud Storage
RulesTestEnvironment.clearStorage() => Promise<void>
Этот метод очищает объекты и метаданные в сегментах хранилища, принадлежащих идентификатору projectId
настроенному для эмулятора Cloud Storage .
RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;
Этот метод возвращает экземпляр хранилища, настроенный для подключения к эмулятору. Этот метод принимает URL-адрес gs://
в сегменте хранилища Firebase для тестирования. Если указано, возвращает экземпляр хранилища для эмулируемой версии имени сегмента.
Запускайте локальные модульные тесты с помощью 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
Используйте это, чтобы установить правила вашей базы данных.
Отправляет правила в локально работающую базу данных. Принимает объект параметров, который определяет ваше «имя базы данных» и ваши «правила» в виде строк.
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» и ваши «правила» в виде строк.
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
Используйте это, чтобы установить правила вашей базы данных.
Отправляет правила в локально работающую базу данных. Принимает объект параметров, который определяет ваше «имя базы данных» и ваши «правила» в виде строк.
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» и ваши «правила» в виде строк.
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());