Advanced Guides
Integration und Testen von Parse Cloud Code-Funktionen
35 min
wie man tests in ihre parse cloud code funktionen integriert einfĂŒhrung dies ist ein leitfaden, der von https //github com/considine , unserem gastautor und leitenden entwickler bei https //koptional com/ das tutorial behandelt, wie man automatisierte tests fĂŒr ihren back4app cloud code einrichtet wir werden kurz darĂŒber sprechen, wie man einen teil ihres client parse codes in die cloud verschiebt, und dann darĂŒber, wie man ihr projekt mit einem test ökosystem integriert sie können auch das beispielprojekt https //github com/back4app/template cloud code unit test direkt fĂŒr eine funktionierende version ĂŒberprĂŒfen ziele wir hoffen, die robusten, skalierbaren aspekte automatisierter tests mit der entwicklerfreundlichen parse umgebung zu kombinieren durch die nutzung von cloud code, vielleicht ein unterbewertetes feature von parse, können entwickler weiterhin schnell ihren code iterieren und sich darauf verlassen, dass die software wie erwartet funktioniert testgetriebene entwicklung https //en wikipedia org/wiki/test driven development ist ein riesiges feld; anstatt philosophisch ĂŒber tests zu sprechen, werden wir eine implementierung durchgehen und ĂŒber einige strategien sprechen (zum beispiel stubbing) voraussetzungen um dieses tutorial abzuschlieĂen, benötigen sie eine app bei back4app befolgen sie das tutorial zur erstellung einer neuen app um zu lernen, wie man eine app bei back4app erstellt back4app befehlszeile, die mit dem projekt konfiguriert ist befolgen sie das tutorial zur einrichtung von cloud code um zu lernen, wie man cloud code fĂŒr ein projekt einrichtet npm auf ihrer befehlszeile installiert hinweis diese bibliothek wird die https //www promisejs org/ , die nicht zu kompliziert sein sollte lass uns ein grundlegendes backend fĂŒr soziale medien erstellen ok! stell dir eine social media anwendung vor, die ein profilmodell zusammen mit dem benutzermodell enthĂ€lt fĂŒr einige apps kannst du profilinformationen im benutzermodell unterbringen, obwohl dies in vielen fĂ€llen nicht effizient ist; du musst oft die belange der autorisierung/authentifizierung von benutzerinhalten trennen und somit zwei verschiedene modelle beibehalten in diesem tutorial werden wir eine funktion implementieren, die die erstellung von benutzern und profilen auf diese weise verwaltet und dabei die belastung fĂŒr den client minimal hĂ€lt lass uns anfangen! 1\ unsere funktionen definieren dies setzt voraus, dass du ein back4app projekt erstellt hast und das befehlszeilenwerkzeug installiert ist (siehe voraussetzungen) fĂŒr beispiele von frontend code wird dieser leitfaden auf die syntax des parse javascript sdk zur vereinfachung verweisen wenn sich jemand fĂŒr diese anwendung anmeldet, sollte ein profil erstellt und mit dem benutzerobjekt verknĂŒpft werden die anmeldefunktion in vielen parse anwendungen erstellen sie den benutzer mit der folgenden syntax 1 var user = new parse user(); 2 user set("username", "my name"); 3 user set("password", "my pass"); 4 user set("email", "email\@example com"); in unserem fall möchten wir auch ein profil initialisieren und es auf das benutzerobjekt verweisen parse server 3 x 1 try { 2 await user signup(null, {usemasterkey true}); 3 let profile = parse object extend("profile"); 4 let profile = new profile({ 5 firstname params firstname, 6 lastname params lastname, 7 user user 8 }) 9 return profile save(null, {usemasterkey true}); 10 } catch (err){ 11 return (err message); 12 } parse server 2 x 1 user signup(null, { 2 success function (newuser) { 3 var profile = parse object extend("profile"); 4 var profile = new profile(); 5 profile set("firstname", "john"); 6 profile set("lastname", "smith"); 7 profile set("user", newuser); 8 profile save(); 9 }, 10 error function (err) { 11 // handle error 12 } 13 }) sie könnten diese syntax auf etwas wie folgt verkĂŒrzen parse server 3 x 1 let user = new parse user({ 2 username params username, 3 password params password, 4 email params email 5 }); 6 7 try { 8 await user signup(null, {usemasterkey true}); 9 let profile = parse object extend("profile"); 10 let profile = new profile({ 11 firstname params firstname, 12 lastname params lastname, 13 user user 14 }) 15 return profile save(null, {usemasterkey true}); 16 } catch (err){ 17 return (err message); 18 } parse server 2 x 1 var user = new parse user({ 2 username params username, 3 password params password, 4 email params email 5 }); 6 user signup(null) 7 then((newuser) => { 8 var profile = parse object extend("profile"); 9 var profile = new profile({ 10 "firstname" "john", 11 "lastname" "smith", 12 "user" newuser 13 }); 14 return profile save(); 15 }) leider erfordert dies immer noch, zwei separate anfragen an den parse server zu stellen, was fĂŒr ein frontend ineffizient ist; es ist klug, mehrstufige client server kommunikationsflĂŒsse, wenn möglich, zu vermeiden auch in bezug auf die sicherheit gibt der obige code den erstellungsprozess in die hĂ€nde des clients, was nie klug ist wir möchten verhindern, dass unsere datenintegritĂ€t davon abhĂ€ngt, dass ein client alle schritte eines flusses ordnungsgemÀà abschlieĂt sie könnten beispielsweise eine benutzerdefinierte anfrage senden, die einen benutzer ohne profil erstellt und die persistenten daten der app beschĂ€digt warum nicht alles in einem schritt mit cloud code erledigen? es kann eine aufblĂ€hung des frontend codes verhindern und sicherstellen, dass der client keine unnötige/unsichere arbeit verrichtet! hier ist, was wir stattdessen vom client fĂŒr die anmeldung tun möchten 1 parse cloud run('signupuser', 2 { 3 username 'myname', 4 password "mypass", 5 email "email\@example com", 6 firstname "john", 7 lastname "smith" } 8 ) then(function(newuser) { 9 10 }); parse definiert auch fĂŒr http //docs parseplatform org/cloudcode/guide/#beforesave triggers trigger, die die erstellung des profils ermöglichen, wenn sich der benutzer anmeldet durch die verwendung einer funktion können wir intuitiv die attribute firstname und lastname ĂŒbergeben, die das profil verwenden wird cloud code anmeldefunktion lass uns anfangen! wechsle in dein projektverzeichnis, das mit back4app synchronisiert ist (siehe voraussetzungen, wenn du nicht weiĂt, was das bedeutet) wir gehen von der folgenden struktur aus in unserem fall haben wir bei der initialisierung âcloudâ als unseren verzeichnisnamen gewĂ€hlt ihr verzeichnis kann genannt werden, wie sie möchten parse server 3 x main js 1 parse cloud define("signuserup", async(request) => { 2 // make sure the necessary parameters are passed first 3 let params = request params; 4 if (!params username || !params email || !params password || !params firstname || !params lastname) 5 throw new error("missing parameters need username, email, password, firstname, & lastname"); 6 7 // execute the signup flow 8 let user = new parse user({ 9 username params username, 10 password params password, 11 email params email 12 }); 13 14 try { 15 await user signup(null, {usemasterkey true}); 16 let profile = parse object extend("profile"); 17 let profile = new profile({ 18 firstname params firstname, 19 lastname params lastname, 20 user user 21 }) 22 return profile save(null, {usemasterkey true}); 23 } catch (err){ 24 return (err message); 25 } 26 }); parse server 2 x main js 1 parse cloud define("signuserup", function(request, response) { 2 // make sure the necessary parameters are passed first 3 var params = request params; 4 if (!params username || !params email || !params password || !params firstname || !params lastname) 5 return response error("missing parameters need username, email, password, firstname, & lastname"); 6 7 // execute the signup flow 8 var user = new parse user({ 9 username params username, 10 password params password, 11 email params email 12 }); 13 user signup(null, {usemasterkey true}) 14 then((newuser) => { 15 var profile = parse object extend("profile"); 16 var profile = new profile({ 17 firstname params firstname, 18 lastname params lastname, 19 user newuser 20 }) 21 return profile save(null, {usemasterkey true}); 22 }) 23 then((prof) => response success(prof)) 24 catch((e) => { 25 response error(e message); 26 }) 27 }); sie werden möglicherweise bemerken, dass die option âusemasterkeyâ ĂŒbergeben wird; dies ermöglicht es dem cloud code, alle rollen oder acls zu ĂŒberschreiben, die möglicherweise vorhanden sind da der client diesen code nicht berĂŒhrt, besteht kein risiko, dass er unseren server ĂŒbernimmt bitte seien sie jedoch vorsichtig mit diesem flag! falls es nicht offensichtlich ist, warum dies vorzuziehen sein könnte, anstatt diese funktionalitĂ€t im client code zu platzieren, hier sind einige vorteile lagert die berechnung auf den server und nicht auf das gerĂ€t aus definiert ausdrĂŒcklich die funktionalitĂ€t eines prozesses es ist einfacher, fehlersichere funktionen zu erstellen gibt dem client eine intuitive schnittstelle dies verhindert die möglichkeit, dass ein client einen prozess âhalb erledigtâ 2\ umstrukturierung unserer verzeichnisstruktur super, wir haben zwei cloud funktionen erstellt wir könnten diese funktionen offensichtlich testen, indem wir sie ausfĂŒhren und das parse dashboard ĂŒberprĂŒfen, aber das ist nicht skalierbar oder effizient stattdessen wollen wir automatisierte tests speziell fĂŒr die methoden erstellen, die kontinuierlich ausgefĂŒhrt werden können daher werden wir unseren code ein wenig aufteilen wir werden die funktionen, die wir in main js erstellt haben, in eine neue datei namens cloud functions js (im selben verzeichnis) verschieben dann werden wir importieren diese funktionen in main und sie an die cloud funktionsdefinitionen binden die idee ist, die funktionen von der cloud schnittstelle zu entkoppeln , damit wir sie testen können, ohne ineffizient http anfragen zu senden das wird viel sinn machen, wĂ€hrend wir die testsuite erstellen erstelle die funktionsdatei vielleicht ist dir bewusst, dass du ârequireâ in node js verwenden kannst, um funktionen, objekte und variablen aus anderen dateien zu importieren wir werden somit funktionen definieren, die den parse cloud funktionen entsprechen, die wir in schritt 1 erstellt haben ein möglicherweise verwirrender punkt ist, dass die funktionen, die wir definieren, funktionen zurĂŒckgeben , die dann in die parse cloud definition integriert werden können es mag seltsam erscheinen, eine funktion zu verwenden, um eine funktion zurĂŒckzugeben, aber dies gibt uns die möglichkeit, spĂ€ter beim schreiben unserer tests parse server auszutauschen vielleicht ist dir aufgefallen, dass du das parse objekt in deinem cloud code verwenden kannst, ohne es jemals definieren oder importieren zu mĂŒssen dies liegt daran, dass der server, der diesen code ausfĂŒhrt, parse automatisch hinzufĂŒgt wenn wir jedoch tests fĂŒr die funktionen lokal ausfĂŒhren möchten, haben wir keinen zugriff auf eine instanz tatsĂ€chlich möchten wir unsere eigene instanz bereitstellen, die einem test parse server entspricht, bei dem es keinen schaden anrichtet, wenn daten erstellt oder gelöscht werden jede funktion akzeptiert âparseâ als parameter und gibt die cloud funktionen zurĂŒck parse server 3 x cloud functions js 1 // cloud functions js 2 module exports signupuser = function(parse) { 3 return async(request) => { 4 // copied from main js 5 // make sure the necessary parameters are passed first 6 let params = request params; 7 if (!params username || !params email || !params password || !params firstname || !params lastname) 8 throw new error("missing parameters need username, email, password, firstname, & lastname"); 9 10 // execute the signup flow 11 let user = new parse user({ 12 username params username, 13 password params password, 14 email params email 15 }); 16 17 try { 18 await user signup(null, {usemasterkey true}); 19 let profile = parse object extend("profile"); 20 let profile = new profile({ 21 firstname params firstname, 22 lastname params lastname, 23 user user 24 }) 25 return profile save(null, {usemasterkey true}); 26 } catch (err){ 27 return (err message); 28 } 29 } 30 } parse server 2 x cloud functions js 1 // cloud functions js 2 module exports signupuser = function(parse) { 3 return function (request, response) { 4 // copied from main js 5 // make sure the necessary parameters are passed first 6 var params = request params; 7 if (!params username || !params email || !params password || !params firstname || !params lastname) 8 return response error("missing parameters need username, email, password, firstname, & lastname"); 9 // execute the signup flow 10 var user = new parse user({ 11 username params username, 12 password params password, 13 email params email 14 }); 15 user signup(null, {usemasterkey true}) 16 then((newuser) => { 17 var profile = parse object extend("profile"); 18 var profile = new profile({ 19 firstname params firstname, 20 lastname params lastname, 21 user newuser 22 }) 23 return profile save(null, {usemasterkey true}); 24 }) 25 then((prof) => response success(prof)) 26 catch((e) => { 27 response error(e message); 28 }) 29 } 30 } in main js entfernen sie alles vorherige importieren sie die cloud funktion und binden sie die funktion an die definition der cloud funktion wie folgt 1 // main js 2 var cloudfunctions = require(" /cloud functions"); 3 // note that we are injecting the parse instance, which is automatically supplied in the 4 // context of parse cloud code, but not on local tests 5 parse cloud define("signuserup", cloudfunctions signupuser(parse)); groĂartig! wir haben die funktionalitĂ€t seit schritt 1 ĂŒberhaupt nicht geĂ€ndert, aber wir haben die funktion vom cloud code entkoppelt im nĂ€chsten schritt werden wir einen unit test erstellen! 3\ erstellen sie die test suite fĂŒr unsere test suite werden wir jasmine https //jasmine github io/ , das beliebte test framework, verwenden unser code ist jedoch bisher völlig unabhĂ€ngig von unseren tests, sodass sie jedes framework oder jede plattform verwenden können, die sie bevorzugen lassen sie uns jasmine und jasmine node (eine integration von jasmine und unserer node js umgebung) installieren jetzt installieren wir zwei bibliotheken, die unser test framework verwenden wird es wird das parse sdk verwenden, um sich mit einem gefĂ€lschten parse server zu verbinden, und die events bibliothek, um das anfrageobjekt zu stubben jetzt, mit dem jasmine utility, lassen sie uns unser testverzeichnis initialisieren wenn sie möchten, können sie jasmine global installieren mit $ npm install g jasmine $ npm install g jasmine , dann können sie mit diesem $ jasmine init $ jasmine init dieser leitfaden geht davon aus, dass sie jasmine nicht global installieren, obwohl es empfohlen wird wenn sie dies tun, können sie alle vorkommen von â/node modules/jasmine/bin/jasmine jsâ einfach durch âjasmineâ ersetzen dies sollte ein verzeichnis namens spec erstellen, das selbst einen support ordner enthĂ€lt, der konfigurationsinformationen fĂŒr jasmine enthĂ€lt standardmĂ€Ăig weiĂ jasmine, dass es nach dateien suchen soll, die mit der erweiterung â spec jsâ enden, also werden wir unsere tests entsprechend benennen erstellen sie die datei fĂŒr unseren ersten unit test fĂŒgen sie ein verzeichnis fĂŒr hilfsfunktionen mit zwei dateien hinzu, die uns bei unseren tests helfen werden erstellen sie schlieĂlich eine konstanten datei im selben verzeichnis die funktionalitĂ€t dieser datei wird spĂ€ter erklĂ€rt so sollte ihr verzeichnis jetzt aussehen 4\ austausch eines test parse servers testen rund um parse da unsere methoden einen parse server beinhalten, möchten wir in der lage sein, diese interaktion zu testen es gibt zwei möglichkeiten, dies zu tun a wir können das parse sdk objekt âstubbenâ, indem wir ein objekt definieren, das dasselbe interface implementiert dann ĂŒbergeben wir einfach dieses objekt als parameter an unsere cloud methoden das könnte ungefĂ€hr so aussehen 1 var parsestub = { 2 // make sure all used methods and properties are defined 3 user function () { 4 // constructor function 5 this set = function (key, val) { 6 // logic here to implement the parse object set 7 } 8 } 9 } 10 signupuser(parsestub); // returns cloud function that we can test b ein weiterer ansatz besteht darin, einen echten parse server einzurichten, der nur fĂŒr testdaten dient dies wird die langsame http schicht beinhalten, die parse verwendet, ermöglicht uns jedoch auch, die daten in der datenbank zu testen in unseren tests mĂŒssten wir das parse sdk importieren und es mit einem testserver konfigurieren die beiden stellen, die beim testen von cloud code stubbed werden können a ) stubben eines parse sdk, das keine http anfragen stellt, oder b ) austausch gegen eine testdatenbankimplementierung keiner dieser ansĂ€tze ist die ârichtigeâ antwort es hĂ€ngt davon ab, was sie testen möchten das stubben des interfaces fĂŒr das parse sdk (auch nur der teile, die wir verwenden) ist viel arbeit darĂŒber hinaus werden wir in diesem beispiel die persistenz der daten nach dem speichern testen, daher werden wir den zweiten ansatz verwenden lass uns einen test parse server auf back4app erstellen die anwendungs id und den master schlĂŒssel abrufen und in unserer konstanten datei speichern das parse sdk in unserer spezifikationsdatei initialisieren, damit unser test den testserver verwendet sie sind herzlich eingeladen, einen lokalen parse server https //github com/parse community/parse server fĂŒr ihre tests auszufĂŒhren wir werden einfach eine weitere back4app anwendung in unserem dashboard erstellen wenn sie eine auffrischung benötigen, wie sie einen weiteren back4app server bereitstellen, gehen sie zum tutorial âneue app erstellenâ https //www back4app com/docs/get started/new parse app nennen sie ihre anwendung, wie sie möchten, obwohl es klug sein könnte, etwas wie testbackend zu verwenden dann holen sie sich einfach die anwendungs id und den master schlĂŒssel aus dashboard > app einstellungen > sicherheit & schlĂŒssel speichern sie diese tokens jetzt in unserer konstanten datei wie folgt 1 // /spec/constants js 2 // paste in your app id and master key where the strings are 3 module exports = { 4 application id "paste your application key here", 5 master key "paste your master key here" 6 } geben sie nicht die anwendungs id und den master schlĂŒssel ihrer produktions app ein!!! wir werden daten löschen, und dies könnte dazu fĂŒhren, dass sie daten verlieren 5\ testwerkzeuge cloud funktionen werden als parameter in den express anforderungs und antwortobjekten ĂŒbergeben der server erstellt diese parameter automatisch, wenn sie in der cloud ausgefĂŒhrt werden, daher mĂŒssen wir fĂŒr unsere testumgebungen doubles erstellen dieser fall ist einfacher wenn eine cloud funktion aufgerufen wird, werden daten ĂŒbergeben; in unserem fall werden das profil und die benutzerinformationen ĂŒbergeben jedes bereitgestellte argument ist ĂŒber die eigenschaft request params zugĂ€nglich wenn wir also eine cloud funktion wie 1 // client code, calling parse function 2 parse cloud run('fakefunction', 3 { 4 data1 'i am data1', 5 data2 { 6 prop "nested property" 7 } 8 } 9 ); dann wird die request params eigenschaft die ĂŒbergebenen daten enthalten 1 // server code, running the parse function 2 console log(request params); 3 // { 4 // data1 'i am data1', 5 // data2 { 6 // prop "nested property" 7 // } 8 // } einfach genug, fĂŒr unsere tests sollte das erste argument beim aufrufen unserer cloud funktion die form haben 1 { 2 params { 3 username 'testuser', 4 firstname "john", 5 // the rest of the arguments 6 } 7 } daher mĂŒssen wir in diesem fall kein spezielles mock objekt erstellen das antwortobjekt ermöglicht es dem cloud code, eine http antwort an den client zu senden, die entweder einen erfolg oder einen fehler darstellt wir möchten wissen, wie man den aufruf der cloud funktion nennt unten ist ein mock objekt https //msdn microsoft com/en us/library/ff650441 aspx aufgefĂŒhrt, das es unserem test ermöglicht, zu bestimmen, ob der aufruf erfolgreich war oder nicht wenn das verwirrend ist, keine sorge, legen sie es einfach in ihre /spec/utils/response stub js datei 1 // /spec/utils/response stub js 2 const eventemitter = require('events'); 3 / 4 wrapper around response stub simplifies testing cloud functions that 5 employ a response parameter 6 / 7 function responsestub () { 8 this responselistener = new eventemitter(); 9 this responsestub = {}; 10 / 11 success method that cloud functions expect 12 / 13 this responsestub success = (resp) => { 14 this responselistener emit("success", resp); 15 } 16 / 17 error method that cloud functions expect 18 / 19 this responsestub error = (resp) => { 20 this responselistener emit("error", resp); 21 } 22 / 23 listens for errors and successes from stub and returns promise that resolves or rejects accordingly 24 / 25 this resolver = new promise((resolve, reject) => { 26 this responselistener on("success", (resp) => resolve(resp)); 27 this responselistener on("error", (err) => reject(err)); 28 }); 29 } 30 31 / 32 reeturns stub to feed to cloud function 33 / 34 responsestub prototype getstub = function () { 35 return this responsestub; 36 } 37 38 / 39 returns promise that will indicate the success or failure 40 / 41 responsestub prototype oncomplete = function () { 42 return this resolver; 43 } 44 45 module exports = responsestub; kurz gesagt, diese javascript konstruktorfunktion bietet eine möglichkeit fĂŒr unseren test, ein antwortobjekt zu ĂŒbergeben, das durch die auflösung / ablehnung des promises anzeigt, ob die cloud funktion einen erfolg oder einen fehler zurĂŒckgegeben hĂ€tte datenbank bereinigen offensichtlich möchten wir nicht, dass unsere test parse datenbank das, was wĂ€hrend eines tests angesammelt wird, speichert lassen sie uns ein dienstprogramm zum löschen von datenbanktabellen definieren, das vor (oder nach) testfĂ€llen aufgerufen werden kann fĂŒgen sie folgendes zu âspec/utils/purge parse table jsâ hinzu 1 // spec/utils/purge parse table js 2 / 3 removes all rows from the parse database 4 @param {string} tablename the name of the parse table to be purged 5 @return {promise} promise to destroy each item in the table 6 / 7 module exports = function (parse) { 8 return (tablename) => { 9 var tablequery; 10 if (tablename === "user") 11 tablequery = new parse query(parse user); 12 else tablequery = new parse query(tablename); 13 return tablequery find({usemasterkey true}) then((items) => { 14 var destroyqueue = \[]; 15 for (var i=0; i\<items length; i++) { 16 destroyqueue push(items\[i] destroy({usemasterkey true})); 17 } 18 return promise all(destroyqueue) catch((e) => {console log("error destroying " + e message)}); 19 }); 20 } 21 } nachdem sie diese funktion definiert haben, ist es eine gute zeit, sie daran zu erinnern, sicherzustellen, dass ihre spec/utils/constants js auf ihre test parse anwendung und nicht auf ihre produktions parse anwendung konfiguriert ist dies wird daten löschen, also bestĂ€tigen sie bitte, dass dies die leere datenbank ist, die sie oben erstellt haben diese funktion akzeptiert unser konfiguriertes parse sdk und gibt eine andere funktion zurĂŒck die zurĂŒckgegebene funktion akzeptiert einen tabellennamen und entfernt alle daten aus der entsprechenden parse tabelle wiederum mag die idee, eine funktion zurĂŒckzugeben, seltsam erscheinen, aber sie ermöglicht es der test spezifikation, den parse endpunkt zu konfigurieren und dann auf eine funktion zu verweisen, die die tabelle diesen parse endpunkts löscht super! jetzt lass uns unseren test schreiben! 6\ testen sie, dass die cloud funktion einen fehler sendet, wenn die richtigen parameter nicht ĂŒbergeben werden die cloud funktion ist auf bestimmte parameter angewiesen, die enthalten sein mĂŒssen und sollte fehlschlagen, wenn beispielsweise der âvornameâ nicht gesendet wurde lassen sie uns sicherstellen wir werden unsere testdatei (endlich!) spec/signup user spec js bearbeiten hier ist, was passieren muss, bevor die testdefinitionen importiere das parse nodejs sdk importiere unsere konstanten und konfiguriere das parse sdk, um auf unseren testserver zu zeigen importiere unsere cloud funktion importiere unser âpurge tableâ hilfsprogramm importiere das response mock object, das wir erstellt haben das folgende wird ausreichen 1 // hook into your testing server 2 var parse = require('parse/node'); 3 var constants = require(" /constants"); 4 // head over to your parse dash board for your test server, and grab your keys swap out the strings with the place holders below 5 parse initialize(constants application key, null, constants master key); 6 // if you are running a localhost parse server, set the serverurl accordingly 7 parse serverurl = 'https //parseapi back4app com' 8 var signupuser = require(" /cloud/cloud functions") signupuser(parse); 9 var purgetable = require(" /utils/purge parse table")(parse); 10 var responsestub = require(" /utils/response stub"); jetzt lass uns die testfĂ€lle hinzufĂŒgen die jasmine einfĂŒhrung https //jasmine github io/2 1/introduction könnte helfen, die struktur besser zu verstehen, aber sie sieht so aus (aus der einfĂŒhrung entnommen) die describe blöcke kapseln test suiten, und die âitâ blöcke reprĂ€sentieren fĂ€lle und erwartungen durch das ĂŒbergeben eines parameters an die âitâ blöcke kannst du tests asynchron ausfĂŒhren der test wird nicht abgeschlossen, bis der parameter so aufgerufen wird das ist hilfreich, da einer unserer tests http verwenden wird, und daher auf diese weise asynchron ausgefĂŒhrt werden sollte, da die verwendung von http ein nicht blockierendes verfahren in nodejs ist zusĂ€tzlich ermöglicht jasmine spezielle blöcke innerhalb von suiten, die zu verschiedenen zeitpunkten im testlebenszyklus ausgefĂŒhrt werden können wir möchten alle tabellen vor jedem test löschen, daher werden wir den bereinigungscode im beforeeach block ausfĂŒhren genug geredet, lass uns etwas code hinzufĂŒgen! fĂŒge den folgenden code in deine spec/signup user spec js ein, unter die bereits hinzugefĂŒgten importe 1 //spec/signup user spec js 2 // imports above 3 describe("signupuser", ()=> { 4 beforeeach((done) => { 5 /// purge the user and profile tables, and then proceed 6 promise all(\[purgetable("user"), purgetable("profile")]) 7 catch((e) => fail(e)) 8 then(() => done()); 9 }); 10 it ("should reject a request to signup that does not contain all the parameters", (done) => { 11 var responsestub = new responsestub(); 12 responsestub oncomplete() 13 then(() => fail("should have failed due to invalid parameters")) 14 catch((e) => {}) 15 then(() => done()); 16 17 signupuser({ params {}}, responsestub getstub()); 18 19 }); 20 }); toll, unser erster test ist bestanden im beforeeach block löschen wir die benutzer und profiltabellen dann wird der erste testfall ausgelöst er ĂŒberprĂŒft, dass das ĂŒbergeben ungĂŒltiger parameter an die funktion signupuser dazu fĂŒhrt, dass die funktion einen fehler sendet es verwendet den antwortstub, um sicherzustellen, dass die funktion letztendlich abgelehnt wurde da 'signupuser' fehlschlagen wird, sollte der anfĂ€ngliche 'then' block auf dem stub nicht aufgerufen werden wenn dies der fall ist, schlĂ€gt unser test fehl! fĂŒhre den test mit folgendem befehl aus du solltest die folgende ausgabe sehen 7\ ein test zur datenpersistenz hoffentlich haben sie noch einen weiteren test in sich! wir werden ĂŒberprĂŒfen, dass, wenn unsere cloud funktion ordnungsgemÀà ausgefĂŒhrt wird, unsere datenbank wie erwartet sein wird ein profil wird existieren, mit einem verweis auf ein benutzerobjekt, beide mit den erwarteten attributen fĂŒgen sie den folgenden block zu unserem bestehenden âdescribeâ suite block hinzu 1 //spec/signup user spec js 2 // inside describe 3 it ("should signup a user, and also create a profile that contains a reference to the user", (done) => { 4 var responsestub = new responsestub(); 5 var stub = responsestub getstub(); 6 signupuser({ 7 params { 8 firstname "john", 9 lastname "smith", 10 email "jsmith\@example com", 11 username "jsmith1", 12 password "secretcatchphrase1" 13 }, 14 }, 15 stub 16 ); 17 responsestub oncomplete() 18 then((resp) => { 19 var profileq = new parse query("profile"); 20 profileq equalto("lastname", "smith"); 21 return profileq find({usemasterkey true}); 22 }) 23 // check to make sure the profile we retrieve is valid 24 then((profiles) => { 25 if (profiles length === 0) throw new error("no profile's found"); 26 expect(profiles\[0] get('firstname')) tobe("john"); 27 // get the corresponding user 28 return profiles\[0] get("user") fetch({usemasterkey true}) 29 }) 30 // check to make sure the user is what we expect 31 then((user) => { 32 expect(user getusername()) tobe("jsmith1"); 33 }) 34 catch((e) => { 35 console log(e) 36 fail(e); 37 }) 38 then(() => done()); 39 }); ok, das ist viel, also lassen sie uns durchgehen, was passiert wir instanziieren ein antwort mock objekt, wie im ersten testfall dann fĂŒhren wir signupuser mit einem anfrage doppel aus, das gĂŒltige parameter sowie das antwort mock enthĂ€lt (zeilen 6 16) als nĂ€chstes hört dieser code auf die oncomplete methode des mock objekts, die ein promise zurĂŒckgibt das promise wird abgelehnt, wenn ein response error aufgerufen wurde, und aufgelöst, wenn ein response success aufgerufen wurde alle ablehnungen fĂŒhren dazu, dass die kette der promises zum catch block springt daher wird die fail methode im catch block platziert, da der test fehlschlagen sollte, wenn das promise abgelehnt wird die antwort des promises sollte auf das profilobjekt aufgelöst werden sobald es aufgelöst wird, werden wir nach einem profil mit dem gleichen nachnamen suchen, den wir erstellt haben (zeilen 19 21) dann bestĂ€tigt der test, dass der âfirstnameâ des profils der gleiche ist, den wir ĂŒbergeben haben (zeilen 25 26) der nĂ€chste block ruft das benutzerobjekt ab, das mit dem profil verknĂŒpft ist parse objektzeiger werden separat abgerufen, daher ist ein weiterer promise block erforderlich schlieĂlich bestĂ€tigt der code, dass der entsprechende benutzer den benutzernamen hat, der an die signupuser funktion ĂŒbergeben wurde dann endet der test gehen sie voran und fĂŒhren sie die suite noch einmal aus gehen sie voran und fĂŒhren sie den test mit folgendem befehl aus sie sollten die folgende ausgabe sehen fantastisch! wir haben etwas cloud code geschrieben und ein testframework integriert fazit wenn sie sich verloren haben oder einfach nur den code fĂŒr dieses beispiel möchten, gehen sie zum github repo https //github com/back4app/template cloud code unit test befolgen sie die anweisungen zum herunterladen und ausfĂŒhren wenn etwas unklar ist oder nicht funktioniert, kontaktieren sie mich bitte ĂŒber mein gmail, jackconsidine3 ich hoffe, ihnen hat dieses tutorial gefallen und sie haben einige einblicke gewonnen!