Podczas tworzenia aplikacji możesz zablokować dostęp do bazy danych Cloud Firestore. Zanim jednak to zrobisz, musisz mieć bardziej szczegółowe informacjeCloud Firestore Security Rules. Za pomocą Cloud Firestore emulatora możesz nie tylko tworzyć prototypy i testować ogólne funkcje i działanie aplikacji, ale też pisać testy jednostkowe, które sprawdzają działanie Cloud Firestore Security Rules.
Krótkie wprowadzenie
W przypadku kilku podstawowych przypadków testowych z prostymi regułami wypróbuj przykładowy przewodnik.
Zrozumienie Cloud Firestore Security Rules
Wdrażaj Firebase Authentication i Cloud Firestore Security Rules w przypadku bezserwerowego uwierzytelniania, autoryzacji i weryfikacji danych, gdy używasz mobilnych i internetowych bibliotek klienta.
Cloud Firestore Security Rules obejmują 2 elementy:
match
instrukcja identyfikująca dokumenty w bazie danych;allow
wyrażenie, które kontroluje dostęp do tych dokumentów.
Firebase Authentication weryfikuje dane logowania użytkowników i stanowi podstawę systemów dostępu opartych na użytkownikach i rolach.
Każde żądanie bazy danych z Cloud Firestorebiblioteki klienta mobilnego lub internetowego jest sprawdzane pod kątem reguł zabezpieczeń przed odczytaniem lub zapisaniem jakichkolwiek danych. Jeśli reguły odmawiają dostępu do którejkolwiek z określonych ścieżek dokumentów, całe żądanie kończy się niepowodzeniem.
Więcej informacji o usłudze Cloud Firestore Security Rules znajdziesz w artykule Pierwsze kroki w usłudze Cloud Firestore Security Rules.
Instalowanie emulatora
Aby zainstalować emulator Cloud Firestore, użyj interfejsu wiersza poleceń Firebase i uruchom to polecenie:
firebase setup:emulators:firestore
Uruchamianie emulatora
Zacznij od zainicjowania projektu Firebase w katalogu roboczym. Jest to typowy pierwszy krok podczas korzystania z wiersza poleceń Firebase.
firebase init
Uruchom emulator za pomocą tego polecenia. Emulator będzie działać, dopóki nie zakończysz procesu:
firebase emulators:start --only firestore
W wielu przypadkach chcesz uruchomić emulator, przeprowadzić zestaw testów, a następnie zamknąć go po zakończeniu testów. Możesz to łatwo zrobić za pomocą polecenia emulators:exec
:
firebase emulators:exec --only firestore "./my-test-script.sh"
Po uruchomieniu emulator spróbuje działać na porcie domyślnym (8080). Możesz zmienić port emulatora, modyfikując sekcję "emulators"
w pliku firebase.json
:
{ // ... "emulators": { "firestore": { "port": "YOUR_PORT" } } }
Przed uruchomieniem emulatora
Zanim zaczniesz korzystać z emulatora, pamiętaj o tych kwestiach:
- Emulator początkowo wczyta reguły określone w polu
firestore.rules
w plikufirebase.json
. Oczekuje nazwy lokalnego pliku zawierającego Cloud Firestore Security Rules i stosuje te reguły do wszystkich projektów. Jeśli nie podasz lokalnej ścieżki do pliku lub nie użyjesz metodyloadFirestoreRules
opisanej poniżej, emulator będzie traktować wszystkie projekty jako mające otwarte reguły. - Chociaż większość pakietów SDK Firebase działa bezpośrednio z emulatorami, tylko biblioteka
@firebase/rules-unit-testing
obsługuje tworzenie wersji próbnychauth
w regułach zabezpieczeń, co znacznie ułatwia testy jednostkowe. Dodatkowo biblioteka obsługuje kilka funkcji specyficznych dla emulatora, takich jak czyszczenie wszystkich danych, jak wymieniono poniżej. - Emulatory będą też akceptować tokeny uwierzytelniania Firebase w wersji produkcyjnej dostarczane przez pakiety SDK klienta i odpowiednio oceniać reguły, co umożliwia bezpośrednie łączenie aplikacji z emulatorami w testach integracyjnych i ręcznych.
Uruchamianie lokalnych testów jednostkowych
Uruchamianie lokalnych testów jednostkowych za pomocą pakietu SDK w JavaScript w wersji 9
Firebase udostępnia bibliotekę testów jednostkowych reguł zabezpieczeń w pakiecie JavaScript SDK w wersji 9 i w pakiecie SDK w wersji 8. Interfejsy API biblioteki znacznie się od siebie różnią. Zalecamy korzystanie z biblioteki testowej w wersji 9, która jest bardziej usprawniona i wymaga mniej konfiguracji, aby połączyć się z emulatorami, a tym samym bezpiecznie uniknąć przypadkowego użycia zasobów produkcyjnych. Aby zapewnić wsteczną zgodność, nadal udostępniamy bibliotekę testową v8.
- Typowe metody testowania i funkcje narzędziowe w pakiecie SDK w wersji 9
- Metody testowania w emulatorze w pakiecie SDK w wersji 9
Użyj modułu @firebase/rules-unit-testing
, aby korzystać z emulatora działającego lokalnie. Jeśli wystąpią przekroczenia limitu czasu lub błędy ECONNREFUSED
, sprawdź, czy emulator jest uruchomiony.
Zdecydowanie zalecamy korzystanie z najnowszej wersji Node.js, aby móc używać notacji async/await
. Prawie wszystkie działania, które możesz chcieć przetestować, obejmują funkcje asynchroniczne, a moduł testowy jest przeznaczony do pracy z kodem opartym na obietnicach.
Biblioteka testów jednostkowych reguł w wersji 9 zawsze rozpoznaje emulatory i nigdy nie korzysta z zasobów produkcyjnych.
Bibliotekę importujesz za pomocą instrukcji importu modułowego w wersji 9. Przykład:
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.
Po zaimportowaniu implementacja testów jednostkowych obejmuje:
- Tworzenie i konfigurowanie
RulesTestEnvironment
z wywołaniem funkcjiinitializeTestEnvironment
. - Konfigurowanie danych testowych bez uruchamiania reguł za pomocą wygodnej metody, która umożliwia tymczasowe ich pominięcie
RulesTestEnvironment.withSecurityRulesDisabled
. - Konfigurowanie pakietu testów i funkcji wywoływanych przed i po każdym teście z wywołaniami funkcji czyszczących dane testowe i środowisko, np.
RulesTestEnvironment.cleanup()
lubRulesTestEnvironment.clearFirestore()
. - Wdrażanie przypadków testowych, które naśladują stany uwierzytelniania za pomocą funkcji
RulesTestEnvironment.authenticatedContext
iRulesTestEnvironment.unauthenticatedContext
.
Typowe metody i funkcje narzędziowe
Zobacz też metody testowania specyficzne dla emulatora w pakiecie SDK w wersji 9.
initializeTestEnvironment() => RulesTestEnvironment
Ta funkcja inicjuje środowisko testowe do testowania jednostkowego reguł. Najpierw wywołaj tę funkcję, aby skonfigurować test. Aby wykonanie się powiodło, emulatory muszą być uruchomione.
Funkcja akceptuje opcjonalny obiekt definiujący TestEnvironmentConfig
, który może składać się z identyfikatora projektu i ustawień konfiguracji emulatora.
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
Ta metoda tworzy obiekt RulesTestContext
, który działa jak uwierzytelniony użytkownik uwierzytelniania. Żądania utworzone za pomocą zwróconego kontekstu będą miały dołączony token uwierzytelniania. Opcjonalnie możesz przekazać obiekt definiujący niestandardowe roszczenia lub zastąpienia ładunków tokena uwierzytelniania.
Użyj zwróconego obiektu kontekstu testowego w testach, aby uzyskać dostęp do skonfigurowanych instancji emulatora, w tym tych skonfigurowanych za pomocą 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
Ta metoda tworzy RulesTestContext
, który działa jak klient niezalogowany za pomocą uwierzytelniania. Żądania utworzone za pomocą zwróconego kontekstu nie będą miały dołączonych tokenów Uwierzytelniania Firebase.
Użyj zwróconego obiektu kontekstu testowego w testach, aby uzyskać dostęp do skonfigurowanych instancji emulatora, w tym tych skonfigurowanych za pomocą 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()
Uruchom funkcję konfiguracji testu z kontekstem, który zachowuje się tak, jakby reguły zabezpieczeń były wyłączone.
Ta metoda przyjmuje funkcję wywołania zwrotnego, która przyjmuje kontekst Security-Rules-bypassing i zwraca obietnicę. Kontekst zostanie zniszczony po rozwiązaniu lub odrzuceniu obietnicy.
RulesTestEnvironment.cleanup()
Ta metoda usuwa wszystkie obiekty RulesTestContexts
utworzone w środowisku testowym i czyści zasoby bazowe, co umożliwia prawidłowe zakończenie działania.
Ta metoda w żaden sposób nie zmienia stanu emulatorów. Aby zresetować dane między testami, użyj metody czyszczenia danych specyficznej dla emulatora aplikacji.
assertSucceeds(pr: Promise<any>)) => Promise<any>
Jest to funkcja narzędziowa testu.
Funkcja sprawdza, czy podany obiekt Promise opakowujący operację emulatora zostanie rozwiązany bez naruszenia reguł bezpieczeństwa.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
Jest to funkcja narzędziowa testu.
Funkcja sprawdza, czy podany obiekt Promise opakowujący operację emulatora zostanie odrzucony z powodu naruszenia reguł zabezpieczeń.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
Metody specyficzne dla emulatora
Zobacz też częste metody testowania i funkcje narzędziowe w pakiecie SDK w wersji 9.
RulesTestEnvironment.clearFirestore() => Promise<void>
Ta metoda usuwa dane z bazy danych Firestore należące do projektuprojectId
skonfigurowanego na potrzeby emulatora Firestore.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
Ta metoda pobiera instancję Firestore dla tego kontekstu testowego. Zwrócona instancja pakietu Firebase JS Client SDK może być używana z interfejsami API pakietu SDK klienta (modułowego w wersji 9 lub zgodnego z wersją 9).
Wizualizacja ocen reguł
Emulator Cloud Firestore umożliwia wizualizację żądań klientów w interfejsie Pakietu emulatorów, w tym śledzenie oceny reguł zabezpieczeń Firebase.
Otwórz kartę Firestore > Żądania, aby wyświetlić szczegółową sekwencję oceny każdego żądania.
Generowanie raportów z testów
Po przeprowadzeniu zestawu testów możesz uzyskać dostęp do raportów o pokryciu testami, które pokazują, jak oceniana była każda z Twoich reguł zabezpieczeń.
Aby uzyskać raporty, wyślij zapytanie do udostępnionego punktu końcowego na emulatorze podczas jego działania. Wersja do przeglądarki jest dostępna pod tym adresem URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
Reguły zostaną podzielone na wyrażenia i podwyrażenia, nad którymi możesz najechać kursorem, aby uzyskać więcej informacji, w tym liczbę ocen i zwróconych wartości. Aby uzyskać wersję tych danych w formacie JSON, w zapytaniu podaj ten adres URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
Różnice między emulatorem a wersją produkcyjną
- Nie musisz jawnie tworzyć projektu Cloud Firestore. Emulator automatycznie tworzy każdą instancję, do której uzyskuje dostęp.
- Emulator Cloud Firestore nie działa z normalnym przepływem Firebase Authentication.
Zamiast tego w pakiecie Firebase Test SDK udostępniliśmy metodę
initializeTestApp()
w bibliotecerules-unit-testing
, która przyjmuje poleauth
. Utworzony za pomocą tej metody uchwyt Firebase będzie się zachowywać tak, jakby został uwierzytelniony jako podmiot, który podasz. Jeśli przekażesz wartośćnull
, będzie to traktowane jako użytkownik nieuwierzytelniony (np. regułyauth != null
nie będą działać).
Rozwiązywanie znanych problemów
Podczas korzystania z emulatora Cloud Firestore możesz napotkać te znane problemy. Aby rozwiązać problemy z nieprawidłowym działaniem, postępuj zgodnie z poniższymi wskazówkami. Te uwagi zostały napisane z myślą o bibliotece testów jednostkowych reguł bezpieczeństwa, ale ogólne podejścia mają zastosowanie do dowolnego pakietu SDK Firebase.
Zachowanie testu jest niespójne
Jeśli testy czasami przechodzą, a czasami nie, nawet bez wprowadzania w nich żadnych zmian, może być konieczne sprawdzenie, czy są one prawidłowo uporządkowane.
Większość interakcji z emulatorem ma charakter asynchroniczny, więc sprawdź, czy cały kod asynchroniczny jest prawidłowo uporządkowany. Kolejność możesz ustalić, łącząc obietnice lub używając notacji await
.
Sprawdź w szczególności te operacje asynchroniczne:
- Ustawianie reguł zabezpieczeń, np.
initializeTestEnvironment
. - Odczytywanie i zapisywanie danych, np. za pomocą
db.collection("users").doc("alice").get()
. - Oświadczenia operacyjne, w tym
assertSucceeds
iassertFails
.
Testy są zaliczane tylko przy pierwszym wczytaniu emulatora.
Emulator jest stanowy. Przechowuje wszystkie zapisane w niej dane w pamięci, więc wszystkie dane są tracone po wyłączeniu emulatora. Jeśli uruchamiasz kilka testów z tym samym identyfikatorem projektu, każdy test może generować dane, które mogą wpływać na kolejne testy. Aby obejść to zachowanie, możesz użyć jednej z tych metod:
- Używaj unikalnych identyfikatorów projektów w przypadku każdego testu. Pamiętaj, że jeśli zdecydujesz się na to rozwiązanie, w ramach każdego testu musisz wywołać
initializeTestEnvironment
. Reguły są automatycznie wczytywane tylko w przypadku domyślnego identyfikatora projektu. - Zmień strukturę testów, aby nie wchodziły w interakcje z wcześniej zapisanymi danymi (np. używaj innej kolekcji w przypadku każdego testu).
- Usuń wszystkie dane zapisane podczas testu.
Konfiguracja testu jest bardzo skomplikowana
Podczas konfigurowania testu możesz chcieć zmodyfikować dane w sposób, który nie jest dozwolony w przypadku Cloud Firestore Security Rules. Jeśli reguły komplikują konfigurację testu, użyj w niej RulesTestEnvironment.withSecurityRulesDisabled
, aby odczyty i zapisy nie powodowały błędów PERMISSION_DENIED
.
Następnie test może wykonywać operacje jako uwierzytelniony lub nieuwierzytelniony użytkownik, korzystając odpowiednio z RulesTestEnvironment.authenticatedContext
i unauthenticatedContext
. Dzięki temu możesz sprawdzić, czy funkcja Cloud Firestore Security Rules prawidłowo zezwala na różne przypadki lub im zapobiega.