Catch up on everthing we announced at this year's Firebase Summit. Learn more

Создавать модульные тесты

Firebase Local Emulator люкс сделать проще полностью проверить свое приложение функции и поведение . Это также отличный инструмент для проверки настроек правил безопасности Firebase. Используйте эмуляторы Firebase для запуска и автоматизации модульных тестов в локальной среде. Методы, описанные в этом документе, должны помочь вам при создании и автоматизации модульных тестов для вашего приложения, которые проверяют ваши правила.

Если вы еще не сделали, настроить Firebase эмуляторы .

Перед запуском эмулятора

Перед тем, как начать пользоваться эмулятором, имейте в виду следующее:

  • Эмулятор сначала загрузить правила , указанные в firestore.rules или поле «storage.rules» вашего firebase.json файла. Если файл не существует , и вы не используете loadFirestoreRules или метод «loadStorageRules» , как описано ниже, эмулятор обрабатывает все проекты , как имеющие открытые правила.
  • В то время как большинство Firebase SDKs работы с эмуляторами непосредственно, только @firebase/rules-unit-testing библиотеки поддерживает насмешливую auth в правилах безопасности, делая модульные тесты гораздо проще. Кроме того, библиотека поддерживает несколько специфичных для эмулятора функций, таких как очистка всех данных, как указано ниже.
  • Эмуляторы также будут принимать производственные токены Firebase Auth, предоставляемые через клиентские SDK, и соответственно оценивать правила, что позволяет напрямую подключать ваше приложение к эмуляторам при интеграции и ручных тестах.

Отличия эмуляторов баз данных от продакшена

  • Вам не нужно явно создавать экземпляр базы данных. Эмулятор автоматически создаст любой экземпляр базы данных, к которому осуществляется доступ.
  • Каждая новая база данных запускается с закрытыми правилами, поэтому пользователи без прав администратора не смогут читать или писать.
  • Каждая эмулировать база данных применяет план Спарк лимиты и квоты ( в первую очередь, это ограничивает каждый экземпляр до 100 одновременных соединений).
  • Любая база данных будет принимать строку "owner" в качестве администратора токен аутентификации.
  • Эмуляторы в настоящее время не взаимодействуют с другими продуктами Firebase. Примечательно, что обычный процесс аутентификации Firebase не работает. Вместо этого, вы можете использовать initializeTestApp() метод в rules-unit-testing библиотеки, который принимает auth поле. Объект Firebase, созданный с помощью этого метода, ведет себя так, как если бы он успешно прошел аутентификацию как любой объект, который вы предоставляете. Если вы передаете в null , он будет вести себя как неаутентифицированный пользователь ( auth != null правила не получится , к примеру).

Взаимодействие с эмулятором базы данных в реальном времени

Производство Firebase в реальном время экземпляр базы данных доступен на подобласти 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 доступна .

Используйте @firebase/rules-unit-testing модуля для взаимодействия с эмулятором , который работает на местном уровне. Если вы получаете таймаут или ECONNREFUSED ошибки, проверьте , что эмулятор на самом деле работает.

Мы настоятельно рекомендуем использовать последнюю версию Node.js , так что вы можете использовать async/await обозначения. Почти все поведение, которое вы, возможно, захотите протестировать, включает асинхронные функции, а модуль тестирования разработан для работы с кодом на основе Promise.

Библиотека модульного тестирования правил v9 всегда знает об эмуляторах и никогда не затрагивает ваши производственные ресурсы.

Вы импортируете библиотеку с помощью модульных операторов импорта v9. Например:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
  RulesTestEnvironment,
} 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 .
  • Настройка тестовых данных без запуска правил, используя удобный метод , который позволяет временно обойти их, RulesTestEnvironment.withSecurityRulesDisabled .
  • Настройка тестового набора и за испытание перед / после того, как крючки с вызовами , чтобы очистить данные испытаний и окружающей среды, как RulesTestEnvironment.cleanup() или RulesTestEnvironment.clearFirestore() .
  • Реализация тестовых случаев , которые имитируют состояние аутентификации с использованием RulesTestEnvironment.authenticatedContext и RulesTestEnvironment.unauthenticatedContext .

Общие методы и служебные функции

Также смотрите эмулятор специфических методы испытаний в v9 SDK .

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 , который ведет себя как аутентификацию пользователя аутентификации. К запросам, созданным через возвращаемый контекст, будет прикреплен фиктивный токен аутентификации. При желании можно передать объект, определяющий настраиваемые утверждения или переопределения для полезных данных токена проверки подлинности.

Используйте возвращенный тест объект контекста в ваших тестах , чтобы получить доступ к любым экземплярам эмулятора сконфигурированных, в том числе сконфигурировано с 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 , который ведет себя как клиент , который не вошел в через аутентификацию. К запросам, созданным через возвращаемый контекст, не будут прикреплены токены 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>

Это служебная функция тестового примера.

Функция утверждает, что предоставленное обещание, заключающее операцию эмулятора, будет разрешено без нарушений правил безопасности.

await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

assertFails(pr: Promise<any>)) => Promise<any>

Это служебная функция тестового примера.

Функция утверждает, что предоставленное обещание, заключающее операцию эмулятора, будет отклонено с нарушением правил безопасности.

await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });

Специфичные для эмулятора методы

Смотрите также общие методы испытаний и вспомогательные функции в v9 SDK .

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).

База данных в реальном времени

База данных в реальном времени

RulesTestEnvironment.clearDatabase() => Promise<void>

Этот метод удаляет данные в базе данных в реальном времени , которая принадлежит к projectId сконфигурированной для базы данных эмулятора в реальном времени.

RulesTestContext.database(databaseURL?: Firestore.FirestoreSettings) => Firestore;

Получите экземпляр базы данных реального времени для этого тестового контекста. Возвращенный экземпляр Firebase JS Client SDK можно использовать с API-интерфейсами клиентского SDK (модульная версия v9 или совместимость с v9). Метод принимает URL-адрес экземпляра Realtime Database. Если указано, возвращает экземпляр для эмулируемой версии пространства имен с параметрами, извлеченными из URL-адреса.

Облачное хранилище

Облачное хранилище

RulesTestEnvironment.clearStorage() => Promise<void>

Этот метод удаляет объекты и метаданные в ведре хранения , принадлежащем к projectId сконфигурированного для эмулятора Cloud Storage.

RulesTestContext.storage(bucketUrl?: string) => Firebase Storage;

Этот метод возвращает экземпляр хранилища, настроенный для подключения к эмулятору. Метод принимает gs:// URL в хранилище Firebase Ковш для тестирования. Если указано, возвращает экземпляр хранилища для эмулируемой версии имени сегмента.

Запускайте локальные модульные тесты с помощью пакета SDK для JavaScript 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"
});
   

База данных в реальном времени

База данных в реальном времени

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"));

Облачное хранилище

Облачное хранилище

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"
});
   

База данных в реальном времени

База данных в реальном времени

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"));

Облачное хранилище

Облачное хранилище

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());