В процессе разработки приложения вам может потребоваться ограничить доступ к базе данных Cloud Firestore . Однако перед запуском вам понадобятся более детальные Cloud Firestore Security Rules . С помощью эмулятора Cloud Firestore , помимо прототипирования и тестирования общих функций и поведения приложения, вы можете писать модульные тесты, проверяющие поведение ваших Cloud Firestore Security Rules .
Быстрый старт
For a few basic test cases with simple rules, try out the quickstart sample .
Разберитесь Cloud Firestore Security Rules
Implement Firebase Authentication and Cloud Firestore Security Rules for serverless authentication, authorization, and data validation when you use the mobile and web client libraries.
Cloud Firestore Security Rules include two pieces:
- A
matchstatement that identifies documents in your database. - An
allowexpression that controls access to those documents.
Firebase Authentication verifies users' credentials and provides the foundation for user-based and role-based access systems.
Каждый запрос к базе данных из библиотеки мобильного/веб-клиента Cloud Firestore проверяется на соответствие вашим правилам безопасности перед чтением или записью каких-либо данных. Если правила запрещают доступ к любому из указанных путей к документам, весь запрос завершается ошибкой.
Learn more about Cloud Firestore Security Rules in Get started with Cloud Firestore Security Rules .
Установите эмулятор
To install the Cloud Firestore emulator, use the Firebase CLI and run the command below:
firebase setup:emulators:firestore
Запустите эмулятор
Begin by initializing a Firebase project in your working directory. This is a common first step when using the Firebase CLI .
firebase init
Start the emulator using the following command. The emulator will run until you kill the process:
firebase emulators:start --only firestore
In many cases you want to start the emulator, run a test suite, and then shut down the emulator after the tests run. You can do this easily using the emulators:exec command:
firebase emulators:exec --only firestore "./my-test-script.sh"
When started the emulator will attempt to run on a default port (8080). You can change the emulator port by modifying the "emulators" section of your firebase.json file:
{
// ...
"emulators": {
"firestore": {
"port": "YOUR_PORT"
}
}
}Перед запуском эмулятора
Before you start using the emulator, keep in mind the following:
- Эмулятор сначала загрузит правила, указанные в поле
firestore.rulesвашего файлаfirebase.json. Он ожидает имя локального файла, содержащего ваши Cloud Firestore Security Rules , и применит эти правила ко всем проектам. Если вы не укажете путь к локальному файлу или не используете методloadFirestoreRules, как описано ниже, эмулятор будет рассматривать все проекты как имеющие открытые правила. - Хотя большинство SDK Firebase работают с эмуляторами напрямую, только библиотека
@firebase/rules-unit-testingподдерживает имитациюauthв правилах безопасности, что значительно упрощает модульное тестирование. Кроме того, библиотека поддерживает несколько специфических для эмуляторов функций, таких как очистка всех данных, как указано ниже. - Эмуляторы также будут принимать токены Firebase Auth, предоставленные через клиентские SDK, и соответствующим образом оценивать правила, что позволяет напрямую подключать ваше приложение к эмуляторам в интеграционных и ручных тестах.
Запустите локальные модульные тесты
Запускайте локальные модульные тесты с помощью JavaScript SDK версии 9.
Firebase распространяет библиотеку модульного тестирования правил безопасности как с версией 9 JavaScript SDK, так и с версией 8 SDK. API библиотек существенно различаются. Мы рекомендуем библиотеку тестирования версии 9, которая более оптимизирована и требует меньше настроек для подключения к эмуляторам, что позволяет безопасно избежать случайного использования производственных ресурсов. Для обеспечения обратной совместимости мы продолжаем предоставлять библиотеку тестирования версии 8 .
- Common test methods and utility functions in the v9 SDK
- Специфические для эмулятора методы тестирования в SDK версии 9
Use the @firebase/rules-unit-testing module to interact with the emulator that runs locally. If you get timeouts or ECONNREFUSED errors, double-check that the emulator is actually running.
Мы настоятельно рекомендуем использовать последнюю версию Node.js, чтобы вы могли использовать нотацию async/await . Практически все действия, которые вы, возможно, захотите протестировать, связаны с асинхронными функциями, и модуль тестирования разработан для работы с кодом, основанным на промисах.
The v9 Rules Unit Testing library is always aware of the emulators and never touches your production resources.
You import the library using v9 modular import statements. For example:
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.
После импорта реализация модульных тестов включает в себя:
- Creating and configuring a
RulesTestEnvironmentwith a call toinitializeTestEnvironment. - Setting up test data without triggering Rules, using a convenience method that allows you to temporarily bypass them,
RulesTestEnvironment.withSecurityRulesDisabled. - Setting up test suite and per-test before/after hooks with calls to clean up test data and environment, like
RulesTestEnvironment.cleanup()orRulesTestEnvironment.clearFirestore(). - Implementing test cases that mimic authentication states using
RulesTestEnvironment.authenticatedContextandRulesTestEnvironment.unauthenticatedContext.
Общие методы и вспомогательные функции
Also see emulator-specific test methods in the v9 SDK .
initializeTestEnvironment() => RulesTestEnvironment
This function initializes a test environment for rules unit testing. Call this function first for test setup. Successful execution requires emulators to be running.
The function accepts an optional object defining a TestEnvironmentConfig , which can consist of a project ID and emulator configuration settings.
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.
Use the returned test context object in your tests to access any emulator instances configured, including those configured with 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 , который ведет себя как клиент, не авторизованный с помощью аутентификации. Запросы, созданные с использованием возвращенного контекста, не будут содержать прикрепленных токенов Firebase Auth.
Use the returned test context object in your tests to access any emulator instances configured, including those configured with 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()
Run a test setup function with a context that behaves as if Security Rules were disabled.
This method takes a callback function, which takes the Security-Rules-bypassing context and returns a promise. The context will be destroyed once the promise resolves / rejects.
RulesTestEnvironment.cleanup()
This method destroys all RulesTestContexts created in the test environment and cleans up the underlying resources, allowing a clean exit.
This method does not change the state of emulators in any way. To reset data between tests, use the application emulator-specific clear data method.
assertSucceeds(pr: Promise<any>)) => Promise<any>
Это вспомогательная функция для тестового примера.
The function asserts that the supplied Promise wrapping an emulator operation will be resolved with no Security Rules violations.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });assertFails(pr: Promise<any>)) => Promise<any>
Это вспомогательная функция для тестового примера.
The function asserts that the supplied Promise wrapping an emulator operation will be rejected with a Security Rules violation.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });Методы, специфичные для эмулятора
Also see common test methods and utility functions in the v9 SDK .
RulesTestEnvironment.clearFirestore() => Promise<void>
This method clears data in the Firestore database that belongs to the projectId configured for the Firestore emulator.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
This method gets a Firestore instance for this test context. The returned Firebase JS Client SDK instance can be used with the client SDK APIs (v9 modular or v9 compat).
Визуализация оценки правил
The Cloud Firestore emulator lets you visualize client requests in the Emulator Suite UI, including evaluation tracing for Firebase Security Rules.
Open the Firestore > Requests tab to view the detailed evaluation sequence for each request.

Создание отчетов о тестировании
After running a suite of tests, you can access test coverage reports that show how each of your security rules was evaluated.
To get the reports, query an exposed endpoint on the emulator while it's running. For a browser-friendly version, use the following URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
Это разбивает ваши правила на выражения и подвыражения, при наведении курсора мыши на которые отображается дополнительная информация, включая количество вычислений и возвращаемые значения. Для получения необработанных данных в формате JSON добавьте в свой запрос следующий URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
Различия между эмулятором и производственной средой
- You do not have to explicitly create a Cloud Firestore project. The emulator automatically creates any instance that is accessed.
- Эмулятор Cloud Firestore не работает со стандартным процессом Firebase Authentication . Вместо этого в Firebase Test SDK мы предоставили метод
initializeTestApp()в библиотекеrules-unit-testing, который принимает полеauth. Созданный с помощью этого метода дескриптор Firebase будет вести себя так, как если бы он успешно аутентифицировался как предоставленная вами сущность. Если вы передадитеnull, он будет вести себя как неаутентифицированный пользователь (например, правила,auth != null, завершатся ошибкой).
Устранение известных проблем
При использовании эмулятора Cloud Firestore вы можете столкнуться со следующими известными проблемами. Следуйте приведенным ниже инструкциям для устранения любых нештатных ситуаций. Эти заметки написаны с учетом библиотеки модульного тестирования Security Rules, но общие подходы применимы к любому SDK Firebase.
Поведение тестов непоследовательно.
Если ваши тесты иногда проходят, а иногда проваливаются, даже без каких-либо изменений в самих тестах, вам может потребоваться проверить их правильную последовательность. Большинство взаимодействий с эмулятором асинхронны, поэтому дважды проверьте, правильно ли выстроена последовательность всего асинхронного кода. Вы можете исправить последовательность, либо объединяя промисы в цепочку, либо широко используя нотацию await .
In particular, review the following async operations:
- Setting security rules, with, for example,
initializeTestEnvironment. - Reading and writing data, with, for example,
db.collection("users").doc("alice").get(). - Operational assertions, including
assertSucceedsandassertFails.
Tests only pass the first time you load the emulator
Эмулятор является состоятельным. Он хранит все записанные в него данные в памяти, поэтому любые данные теряются при завершении работы эмулятора. Если вы запускаете несколько тестов для одного и того же идентификатора проекта, каждый тест может генерировать данные, которые могут повлиять на последующие тесты. Для обхода этого поведения можно использовать любой из следующих методов:
- Используйте уникальные идентификаторы проектов для каждого теста. Обратите внимание, что если вы решите это сделать, вам потребуется вызывать
initializeTestEnvironmentв рамках каждого теста; правила автоматически загружаются только для идентификатора проекта по умолчанию. - Restructure your tests so they don't interact with previously written data (for example, use a different collection for each test).
- Удалите все данные, записанные во время тестирования.
Настройка тестовой установки очень сложная.
При настройке теста может потребоваться изменить данные способом, который не разрешен Cloud Firestore Security Rules . Если ваши правила усложняют настройку теста, попробуйте использовать RulesTestEnvironment.withSecurityRulesDisabled на этапах настройки, чтобы операции чтения и записи не вызывали ошибки PERMISSION_DENIED .
После этого ваш тест сможет выполнять операции от имени аутентифицированного или неаутентифицированного пользователя, используя RulesTestEnvironment.authenticatedContext и unauthenticatedContext соответственно. Это позволит вам проверить, правильно ли ваши Cloud Firestore Security Rules разрешают/запрещают различные случаи.