Auf dieser Seite werden Best Practices und Tools zum Schreiben von Einheitentests für Ihr
Funktionen wie Tests, die Teil einer kontinuierlichen Integration (CI) sind
System. Um das Testen zu vereinfachen, stellt Firebase die Firebase Test SDK für Cloud Functions bereit. Es
wird auf npm als firebase-functions-test
bereitgestellt und ist ein Companion-Test-SDK
an firebase-functions
. Die Firebase Test SDK für Cloud Functions:
- Es kümmert sich um die angemessene Einrichtung und Bereinigung für Ihre Tests, z. B.
Festlegen und Aufheben der Festlegung von Umgebungsvariablen, die von
firebase-functions
benötigt werden. - Es werden Beispieldaten und Ereigniskontext generiert, sodass Sie nur angeben müssen die für den Test relevant sind.
Einrichtung testen
Installieren Sie sowohl firebase-functions-test
als auch Mocha, ein
Test-Framework, indem Sie die folgenden Befehle im Ordner „Functions“ (Funktionen) ausführen:
npm install --save-dev firebase-functions-test
npm install --save-dev mocha
Als Nächstes erstellen Sie einen test
-Ordner im Ordner „Functions“ (Funktionen) und eine neue Datei.
für den Testcode einfügen und z. B. index.test.js
nennen.
Ändern Sie abschließend functions/package.json
und fügen Sie Folgendes hinzu:
"scripts": {
"test": "mocha --reporter spec"
}
Nachdem Sie die Tests geschrieben haben, können Sie sie ausführen, indem Sie darin npm test
ausführen.
im Funktionsverzeichnis.
Firebase Test SDK wird für Cloud Functions initialisiert
Es gibt zwei Möglichkeiten, firebase-functions-test
zu verwenden:
- Onlinemodus (empfohlen): Tests schreiben, die mit einem Firebase-Projekt interagieren die ausschließlich dem Testen gewidmet ist, damit Datenbankschreibvorgänge, Nutzererstellungen usw. und der Testcode kann die Ergebnisse überprüfen. Das bedeutet auch, dass andere Google SDKs, die in Ihren Funktionen verwendet werden, funktionieren auch.
- Offlinemodus:Erstellen Sie isolierte und Offline-Einheitentests ohne Nebenwirkungen. Das bedeutet, dass alle Methodenaufrufe, die mit einem Firebase-Produkt interagieren (z. B. Schreiben in die Datenbank oder Erstellen eines Nutzers), gestubbt werden müssen. Verwendung im Offlinemodus wird der Modus in der Regel nicht empfohlen, wenn du Cloud Firestore oder Realtime Database hast -Funktionen, da dies die Komplexität des Testcodes erheblich erhöht.
SDK im Onlinemodus initialisieren (empfohlen)
Wenn Sie Tests schreiben möchten, die mit einem Testprojekt interagieren, müssen Sie die Projektkonfigurationswerte angeben, die zum Initialisieren der App über firebase-admin
erforderlich sind, sowie den Pfad zu einer Dienstkontoschlüsseldatei.
So rufen Sie die Konfigurationswerte Ihres Firebase-Projekts ab:
- Öffnen Sie die Projekteinstellungen in der Firebase-Konsole.
- Wählen Sie unter Meine Apps die gewünschte App aus.
Wählen Sie im rechten Bereich die Option zum Herunterladen einer Konfigurationsdatei für Apple- und Android-Apps aus.
Wählen Sie für Web-Apps Config (Konfigurieren) aus, um die Daten aufzurufen. Konfigurationswerte.
So erstellen Sie eine Schlüsseldatei:
- Öffnen Sie den Bereich Dienstkonten. der Google Cloud-Konsole.
- Wählen Sie das Standarddienstkonto App Engine aus und verwenden Sie das Optionsmenü unter und wählen Sie Schlüssel erstellen aus.
- Wenn Sie dazu aufgefordert werden, wählen Sie als Schlüsseltyp JSON aus und klicken Sie auf Erstellen.
Nachdem Sie die Schlüsseldatei gespeichert haben, initialisieren Sie das SDK:
// At the top of test/index.test.js
const test = require('firebase-functions-test')({
databaseURL: 'https://my-project.firebaseio.com',
storageBucket: 'my-project.appspot.com',
projectId: 'my-project',
}, 'path/to/serviceAccountKey.json');
SDK im Offlinemodus initialisieren
Wenn Sie vollständig Offlinetests schreiben möchten, können Sie das SDK initialisieren ohne Parameter:
// At the top of test/index.test.js
const test = require('firebase-functions-test')();
Mocking-Konfigurationswerte
Wenn Sie functions.config()
in Ihrem Funktionscode verwenden, können Sie die Konfiguration simulieren
Werte. Angenommen, functions/index.js
enthält den folgenden Code:
const functions = require('firebase-functions/v1');
const key = functions.config().stripe.key;
Dann können Sie den Wert in Ihrer Testdatei wie folgt simulieren:
// Mock functions config values
test.mockConfig({ stripe: { key: '23wr42ewr34' }});
Funktionen importieren
Verwenden Sie zum Importieren Ihrer Funktionen require
, um Ihre Hauptfunktionsdatei als
-Modul. Führen Sie dies erst nach der Initialisierung von firebase-functions-test
durch.
und simulierte Konfigurationswerte.
// after firebase-functions-test has been initialized
const myFunctions = require('../index.js'); // relative path to functions code
Wenn Sie firebase-functions-test
initialisiert haben in
Offlinemodus und Sie haben
admin.initializeApp()
in den Funktionscode ein, müssen Sie ihn vor dem
Funktionen importieren:
// If index.js calls admin.initializeApp at the top of the file, // we need to stub it out before requiring index.js. This is because the // functions will be executed as a part of the require process. // Here we stub admin.initializeApp to be a dummy function that doesn't do anything. adminInitStub = sinon.stub(admin, 'initializeApp'); // Now we can require index.js and save the exports inside a namespace called myFunctions. myFunctions = require('../index');
Hintergrundfunktionen testen (Nicht-HTTP-Funktionen)
Das Testen nicht HTTP-basierter Funktionen umfasst die folgenden Schritte:
- Umschließen Sie die Funktion, die Sie testen möchten, in der Methode
test.wrap
. - Testdaten erstellen
- Rufen Sie die gewrappte Funktion mit den von Ihnen erstellten Testdaten und allen Ereigniskontextfeldern auf, die Sie angeben möchten.
- Machen Sie Behauptungen zum Verhalten.
Verpacken Sie zunächst die Funktion, die Sie testen möchten. Angenommen, Sie haben in functions/index.js
eine Funktion namens makeUppercase
, die Sie testen möchten. Schreiben Sie den
Follower in functions/test/index.test.js
// "Wrap" the makeUpperCase function from index.js
const myFunctions = require('../index.js');
const wrapped = test.wrap(myFunctions.makeUppercase);
wrapped
ist eine Funktion, die makeUppercase
aufruft, wenn sie aufgerufen wird. wrapped
Für sind zwei Parameter erforderlich:
- data (erforderlich): Die Daten, die an
makeUppercase
gesendet werden sollen. Dies direkt entspricht dem ersten Parameter, der an den Funktions-Handler gesendet wurde, den Sie geschrieben hat.firebase-functions-test
bietet Methoden zum Erstellen benutzerdefinierter Daten oder Beispieldaten. - eventContextOptions (optional): Felder des Ereigniskontexts, die Sie
die Sie angeben möchten. Der Ereigniskontext ist der zweite Parameter, der an den
Funktions-Handler, den Sie geschrieben haben. Wenn Sie kein
eventContextOptions
einfügenwrapped
verwendet wird, wird trotzdem ein Ereigniskontext generiert. mit sinnvollen Feldern. Sie können einige der generierten Felder überschreiben, die hier angegeben werden. Sie müssen nur die Felder einfügen, die Sie überschreiben möchten. Alle Felder, die Sie nicht überschrieben haben, werden generiert.
const data = … // See next section for constructing test data
// Invoke the wrapped function without specifying the event context.
wrapped(data);
// Invoke the function, and specify params
wrapped(data, {
params: {
pushId: '234234'
}
});
// Invoke the function, and specify auth and auth Type (for real time database functions only)
wrapped(data, {
auth: {
uid: 'jckS2Q0'
},
authType: 'USER'
});
// Invoke the function, and specify all the fields that can be specified
wrapped(data, {
eventId: 'abc',
timestamp: '2018-03-23T17:27:17.099Z',
params: {
pushId: '234234'
},
auth: {
uid: 'jckS2Q0' // only for real time database functions
},
authType: 'USER' // only for real time database functions
});
Testdaten erstellen
Der erste Parameter einer umschlossenen Funktion sind die Testdaten zum Aufrufen der zugrunde liegenden mit denen die Funktion funktioniert wird. Es gibt verschiedene Möglichkeiten, Testdaten zu erstellen.
Benutzerdefinierte Daten verwenden
firebase-functions-test
bietet eine Reihe von Funktionen zum Erstellen der benötigten Daten
um Ihre Funktionen zu testen. Verwenden Sie beispielsweise test.firestore.makeDocumentSnapshot
, um eine Firestore-DocumentSnapshot
zu erstellen. Das erste Argument sind die Daten und der
zweites Argument ist der vollständige Referenzpfad und es gibt einen
Optionales drittes Argument
für weitere Attribute des Snapshots, die Sie angeben können.
// Make snapshot
const snap = test.firestore.makeDocumentSnapshot({foo: 'bar'}, 'document/path');
// Call wrapped function with the snapshot
const wrapped = test.wrap(myFunctions.myFirestoreDeleteFunction);
wrapped(snap);
Wenn Sie eine onUpdate
- oder onWrite
-Funktion testen, müssen Sie zwei Snapshots erstellen: einen für den Vorher- und einen für den Nachher-Status. Anschließend können Sie mit der Methode makeChange
ein Change
-Objekt mit diesen Snapshots erstellen.
// Make snapshot for state of database beforehand
const beforeSnap = test.firestore.makeDocumentSnapshot({foo: 'bar'}, 'document/path');
// Make snapshot for state of database after the change
const afterSnap = test.firestore.makeDocumentSnapshot({foo: 'faz'}, 'document/path');
const change = test.makeChange(beforeSnap, afterSnap);
// Call wrapped function with the Change object
const wrapped = test.wrap(myFunctions.myFirestoreUpdateFunction);
wrapped(change);
Ähnliche Funktionen finden Sie in der API-Referenz. für alle anderen Datentypen.
Beispieldaten verwenden
Wenn Sie die in Ihren Tests verwendeten Daten nicht anpassen müssen,
firebase-functions-test
bietet Methoden zum Generieren von Beispieldaten für jede
Funktionstyps aus.
// For Firestore onCreate or onDelete functions
const snap = test.firestore.exampleDocumentSnapshot();
// For Firestore onUpdate or onWrite functions
const change = test.firestore.exampleDocumentSnapshotChange();
In der API-Referenz finden Sie Methoden für für jeden Funktionstyp Beispieldaten abrufen.
Stub-Daten verwenden (für den Offlinemodus)
Wenn du das SDK im Offlinemodus initialisiert hast und einen Cloud Firestore- oder
Realtime Database-Funktion verwenden, sollten Sie ein einfaches Objekt mit Stubs verwenden.
anstatt eine tatsächliche DocumentSnapshot
oder DataSnapshot
zu erstellen.
Angenommen, Sie schreiben einen Einheitentest für die folgende Funktion:
// Listens for new messages added to /messages/:pushId/original and creates an // uppercase version of the message to /messages/:pushId/uppercase exports.makeUppercase = functions.database.ref('/messages/{pushId}/original') .onCreate((snapshot, context) => { // Grab the current value of what was written to the Realtime Database. const original = snapshot.val(); functions.logger.log('Uppercasing', context.params.pushId, original); const uppercase = original.toUpperCase(); // You must return a Promise when performing asynchronous tasks inside a Functions such as // writing to the Firebase Realtime Database. // Setting an "uppercase" sibling in the Realtime Database returns a Promise. return snapshot.ref.parent.child('uppercase').set(uppercase); });
Innerhalb der Funktion wird snap
zweimal verwendet:
snap.val()
snap.ref.parent.child('uppercase').set(uppercase)
Erstellen Sie im Testcode ein einfaches Objekt, bei dem beide Codepfade funktionieren, und verwenden Sie Sinon, um einen Stub für die Methoden auszuführen.
// The following lines creates a fake snapshot, 'snap', which returns 'input' when snap.val() is called, // and returns true when snap.ref.parent.child('uppercase').set('INPUT') is called. const snap = { val: () => 'input', ref: { parent: { child: childStub, } } }; childStub.withArgs(childParam).returns({ set: setStub }); setStub.withArgs(setParam).returns(true);
Assertions erstellen
Nachdem Sie das SDK initialisiert, die Funktionen gekapselt und Daten erstellt haben, können Sie die gekapselten Funktionen mit den erstellten Daten aufrufen und Aussagen zum Verhalten machen. Sie können eine Bibliothek wie Chai für diese Assertions zu treffen.
Assertions im Onlinemodus erstellen
Wenn Sie die Firebase Test SDK für Cloud Functions im Onlinemodus initialisiert haben,
können bestätigen, dass die gewünschten Aktionen (z. B. ein Schreiben in eine Datenbank) durch
mit dem firebase-admin
SDK.
Im folgenden Beispiel wird behauptet, dass 'INPUT' in die Datenbank des Testprojekt.
// Create a DataSnapshot with the value 'input' and the reference path 'messages/11111/original'. const snap = test.database.makeDataSnapshot('input', 'messages/11111/original'); // Wrap the makeUppercase function const wrapped = test.wrap(myFunctions.makeUppercase); // Call the wrapped function with the snapshot you constructed. return wrapped(snap).then(() => { // Read the value of the data at messages/11111/uppercase. Because `admin.initializeApp()` is // called in functions/index.js, there's already a Firebase app initialized. Otherwise, add // `admin.initializeApp()` before this line. return admin.database().ref('messages/11111/uppercase').once('value').then((createdSnap) => { // Assert that the value is the uppercased version of our input. assert.equal(createdSnap.val(), 'INPUT'); }); });
Assertions im Offlinemodus erstellen
Sie können Assertions zum erwarteten Rückgabewert der Funktion machen:
const childParam = 'uppercase'; const setParam = 'INPUT'; // Stubs are objects that fake and/or record function calls. // These are excellent for verifying that functions have been called and to validate the // parameters passed to those functions. const childStub = sinon.stub(); const setStub = sinon.stub(); // The following lines creates a fake snapshot, 'snap', which returns 'input' when snap.val() is called, // and returns true when snap.ref.parent.child('uppercase').set('INPUT') is called. const snap = { val: () => 'input', ref: { parent: { child: childStub, } } }; childStub.withArgs(childParam).returns({ set: setStub }); setStub.withArgs(setParam).returns(true); // Wrap the makeUppercase function. const wrapped = test.wrap(myFunctions.makeUppercase); // Since we've stubbed snap.ref.parent.child(childParam).set(setParam) to return true if it was // called with the parameters we expect, we assert that it indeed returned true. return assert.equal(wrapped(snap), true);
Ihr könnt auch mithilfe von Sinon-Spionen dass bestimmte Methoden aufgerufen wurden und die erwarteten Parameter vorhanden sind.
HTTP-Funktionen testen
Gehe zum Testen von HTTP-onCall-Funktionen genauso vor wie beim Testen von Hintergrundfunktionen.
Wenn Sie HTTP-onRequest-Funktionen testen, verwenden Sie
firebase-functions-test
, wenn:
- Du verwendest
functions.config()
- Ihre Funktion interagiert mit einem Firebase-Projekt oder anderen Google APIs und Sie ein echtes Firebase-Projekt mit den zugehörigen Anmeldedaten für Ihre Tests verwenden möchten.
Eine HTTP-onRequest-Funktion verwendet zwei Parameter: ein Anfrageobjekt und eine Antwort
-Objekt enthält. So können Sie die addMessage()
-Beispielfunktion testen:
- Überschreiben Sie die Weiterleitungsfunktion im Antwortobjekt, da
sendMessage()
sie aufruft. - Verwenden Sie in der Weiterleitungsfunktion chai.assert. um zu behaupten, welche Parameter die Weiterleitungsfunktion verwenden soll, aufgerufen werden durch:
// A fake request object, with req.query.text set to 'input' const req = { query: {text: 'input'} }; // A fake response object, with a stubbed redirect function which asserts that it is called // with parameters 303, 'new_ref'. const res = { redirect: (code, url) => { assert.equal(code, 303); assert.equal(url, 'new_ref'); done(); } }; // Invoke addMessage with our fake request and response objects. This will cause the // assertions in the response object to be evaluated. myFunctions.addMessage(req, res);
Bereinigung testen
Rufen Sie die Bereinigungsfunktion ganz am Ende des Testcodes auf. Dadurch wird die Einstellung aufgehoben
Umgebungsvariablen, die das SDK bei der Initialisierung festgelegt hat, und löscht
Firebase-Apps, die eventuell erstellt wurden, wenn Sie mit dem SDK eine echte
Zeitdatenbank DataSnapshot
oder Firestore DocumentSnapshot
.
test.cleanup();
Vollständige Beispiele ansehen und mehr erfahren
Die vollständigen Beispiele finden Sie im Firebase GitHub-Repository.
- Realtime Database- und HTTP-Funktionen im Onlinemodus testen
- Realtime Database- und HTTP-Funktionen im Offlinemodus testen
Weitere Informationen finden Sie in der API-Referenz.
für firebase-functions-test
.