Advanced Guides
Testing delle Funzioni con Parse Cloud Code su Back4App
35 min
come integrare i test nelle tue funzioni di parse cloud code introduzione questa è una guida scritta da https //github com/considine , il nostro scrittore ospite e sviluppatore principale presso https //koptional com/ il tutorial tratta di come impostare test automatizzati per il tuo cloud code di back4app parleremo brevemente di come spostare parte del tuo codice client di parse nel cloud, e poi di come integrare il tuo progetto con un ecosistema di test puoi anche dare un'occhiata al https //github com/back4app/template cloud code unit test direttamente per una versione funzionante obiettivi speriamo di combinare gli aspetti robusti e scalabili dei test automatizzati con l'ambiente parse amichevole per gli sviluppatori sfruttando il cloud code, forse una funzionalitĂ sottovalutata di parse, gli sviluppatori possono continuare a iterare rapidamente il loro codice e avere la certezza che il software funzionerĂ come previsto https //en wikipedia org/wiki/test driven development è un campo immenso; piuttosto che parlare filosoficamente dei test, passeremo attraverso un'implementazione e parleremo di alcune strategie (stubbing, per esempio) prerequisiti per completare questo tutorial, hai bisogno di un'app su back4app segui il https //www back4app com/docs/get started/new parse app per imparare come creare un'app su back4app back4app command line configurato con il progetto segui il https //www back4app com/docs per imparare come impostare il cloud code per un progetto npm installato sulla tua riga di comando nota questa libreria utilizzerĂ il https //www promisejs org/ , che non dovrebbe essere troppo complicato creiamo un backend di social media di base ok! immagina un'applicazione di social media che include un modello di profilo da affiancare al modello utente per alcune app, potresti inserire le informazioni del profilo nel modello utente, anche se in molti casi questo non è efficiente; spesso sarĂ necessario separare le preoccupazioni di autorizzazione/autenticazione dai contenuti utente, e quindi mantenere due modelli diversi in questo tutorial, implementeremo una funzionalitĂ che gestisce la creazione di utenti e profili in questo modo, ponendo uno sforzo minimo sul client iniziamo! 1\ definire le nostre funzioni questo presuppone che tu abbia creato un progetto back4app e installato lo strumento da riga di comando (vedi requisiti) per esempi di codice frontend, questa guida farĂ riferimento alla sintassi del parse javascript sdk per semplicitĂ quando qualcuno si registra per questa applicazione, dovrebbe essere creato un profilo e accoppiato all'oggetto utente la funzione di registrazione in molte applicazioni parse, creerai l'utente con la seguente sintassi 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"); nel nostro caso, ci piacerebbe anche inizializzare un profilo e collegarlo all'oggetto utente 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 }) potresti accorciare quella sintassi in qualcosa di simile a questo 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 }) sfortunatamente, questo comporta ancora la creazione di due richieste separate al parse server, il che è inefficiente per un frontend; è saggio evitare flussi di comunicazione client server a piĂš passaggi quando possibile inoltre, riguardo alla sicurezza, il codice sopra sta mettendo il processo di creazione nelle mani di un cliente, il che non è mai intelligente vorremmo prevenire che la nostra integritĂ dei dati dipenda dal fatto che un cliente completi correttamente tutti i passaggi di un flusso potrebbero, ad esempio, inviare una richiesta personalizzata che crea un utente senza profilo, corrompendo i dati persistenti dell'app perchĂŠ non fare tutto questo in un solo passaggio utilizzando il codice cloud? può prevenire l'ingrossamento del codice frontend e garantire che il cliente non stia facendo lavoro non necessario/insecure! ecco cosa vogliamo fare invece dal client per la registrazione 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 definisce anche per http //docs parseplatform org/cloudcode/guide/#beforesave triggers trigger, consentendo la creazione del profilo quando l'utente si registra tuttavia, utilizzando una funzione possiamo passare intuitivamente gli attributi firstname e lastname che il profilo utilizzerĂ funzione di registrazione del codice cloud iniziamo! spostati nella directory del tuo progetto che è sincronizzata con back4app (vedi prerequisiti se non sai cosa significa) assumeremo la seguente struttura 1 /cloud 2 /cloud/main js nel nostro caso, all'inizializzazione, abbiamo scelto âcloudâ come nome della directory la tua directory può essere chiamata come vuoi 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 }); potresti notare che l'opzione âusemasterkeyâ viene passata; questo consente al codice cloud di superare eventuali ruoli o acl che potrebbero essere in atto poichĂŠ il client non tocca questo codice, non c'è rischio che possano dirottare il nostro server tuttavia, fai attenzione a questo flag! nel caso non sia ovvio perchĂŠ questo potrebbe essere preferibile rispetto a collocare questa funzionalitĂ nel codice client, ecco alcuni vantaggi scarica il calcolo sul server piuttosto che sul dispositivo definisce esplicitamente la funzionalitĂ di un processo piĂš facile creare funzioni a prova di errore fornisce al cliente un'interfaccia intuitiva questo previene la possibilitĂ che un cliente âfaccia a metĂ â un processo 2\ rifattorizzare la nostra struttura di directory ottimo, abbiamo creato due funzioni cloud ovviamente potremmo testare queste funzioni eseguendole e controllando il parse dashboard, ma ciò non è scalabile o efficiente vogliamo invece creare test automatizzati specificamente per i metodi che possono essere eseguiti continuamente quindi separeremo un po' il nostro codice spostiamo le funzioni che abbiamo creato in main js in un nuovo file chiamato cloud functions js (nella stessa directory) poi importeremo queste funzioni in main e le collegheremo alle definizioni delle funzioni cloud l'idea è di disaccoppiare le funzioni dall'interfaccia cloud in modo da poterle testare senza inviare inefficacemente richieste http questo avrĂ molto senso mentre creiamo il pacchetto di test creare il file delle funzioni \# ricorda, la directory 'cloud' è stata determinata \# quando abbiamo inizializzato la directory con il nostro progetto back4app \# controlla i requisiti se questo non ha senso touch /cloud/cloud functions js potresti essere a conoscenza del fatto che puoi usare ârequireâ in node js per importare funzioni, oggetti e variabili da altri file definiremo quindi funzioni corrispondenti alla funzione cloud di parse che abbiamo creato nel passo 1 un punto potenzialmente confuso è che le funzioni che stiamo definendo saranno funzioni di ritorno , che possono poi essere collegate alla definizione di parse cloud potrebbe sembrare strano usare una funzione per restituire una funzione, ma questo ci darĂ il potere di sostituire i server parse in seguito quando scriviamo i nostri test potresti aver notato che puoi usare l'oggetto parse nel tuo codice cloud, senza mai doverlo definire o importare questo è dovuto al server che esegue questo codice che aggiunge automaticamente parse tuttavia, se vogliamo eseguire test sulle funzioni localmente, non abbiamo a disposizione un'istanza in effetti, ci piacerebbe fornire la nostra istanza che corrisponde a un server parse di test, dove non c'è danno nella creazione o cancellazione di dati quindi ogni funzione accetterĂ âparseâ come parametro e restituirĂ le funzioni cloud 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, rimuovi tutto da prima importa la cloud function e collega la funzione alla definizione della cloud function in questo modo 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)); ottimo! non abbiamo cambiato affatto la funzionalitĂ dal passo 1, ma abbiamo disaccoppiato la funzione dal cloud code nel prossimo passo creeremo un test unitario! 3\ crea il test suite per il nostro test suite utilizzeremo https //jasmine github io/ , il popolare framework di testing tuttavia, il nostro codice finora è completamente agnostico rispetto ai nostri test, quindi puoi utilizzare qualsiasi framework o piattaforma che preferisci installiamo jasmine e jasmine node (un'integrazione di jasmine e del nostro ambiente node js) $ npm install jasmine jasmine node save dev ora installiamo due librerie che il nostro suite di test utilizzerĂ utilizzerĂ il parse sdk per connettersi a un falso parse server e la libreria events per simulare l'oggetto di richiesta $ npm install parse events save dev ora, utilizzando l'utilitĂ jasmine, inizializziamo la nostra directory di test $ /node modules/jasmine/bin/jasmine js init se preferisci, puoi installare jasmine globalmente con $ npm install g jasmine $ npm install g jasmine , poi puoi inizializzare con questo $ jasmine init $ jasmine init questa guida presupporrĂ che tu non installi jasmine globalmente, anche se è consigliato se lo fai, puoi sostituire tutte le istanze di â/node modules/jasmine/bin/jasmine jsâ con semplicemente âjasmineâ questo dovrebbe creare una directory chiamata spec, che include a sua volta una cartella di supporto contenente informazioni di configurazione per jasmine per impostazione predefinita, jasmine sa cercare file che terminano con l'estensione â spec jsâ, quindi nomineremo i nostri test di conseguenza crea il file per il nostro primo test unitario $ # nella directory /spec $ touch signup user spec js' aggiungi una directory utilities con due file che aiuteranno con i nostri test $ # nella directory /spec $ touch utils/purge parse table js $ touch utils/response stub js infine, crea un file constants nella stessa directory l'utilitĂ di questo file sarĂ spiegata in seguito $ # nella directory /spec $ touch constants js ecco come dovrebbe apparire ora la tua directory âââ cloud â âââ cloud functions js â âââ main js âââ node modules âââ spec â âââ support â â âââ jasmine json â âââ utils â â âââ purge parse table js â â âââ response stub js â âââ signup user spec js â âââ constants js 4\ sostituzione con un test parse server testare con parse poichĂŠ i nostri metodi coinvolgono un parse server, vogliamo essere in grado di testare quell'interazione ci sono due modi per farlo a possiamo "stub" l'oggetto parse sdk, definendo un oggetto che implementa la stessa interfaccia poi basta passare quell'oggetto come parametro ai nostri metodi cloud potrebbe apparire qualcosa del genere 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 un altro approccio è impostare un vero server parse che servirĂ solo per i dati di test questo comporterĂ il lento strato http che parse utilizza, ma ci permetterĂ anche di testare i dati nel database nei nostri test dovremmo importare il parse sdk e configurarlo con un server di test i due luoghi che possono essere stub quando si testano i codici cloud a ) stub un parse sdk che non effettuerĂ richieste http, o b ) sostituire con un'implementazione del database di test nessuno di questi approcci è la risposta "giusta" dipende da cosa stai cercando di testare stub l'interfaccia per il parse sdk (anche solo le parti che stiamo usando) è un gran lavoro inoltre, testeremo la persistenza dei dati dopo il salvataggio in questo esempio, quindi utilizzeremo il secondo approccio facciamo crea un server parse di test su back4app prendi l'id dell'applicazione e la chiave master e salvali nel nostro file di costanti inizializza il parse sdk nel nostro file di specifica, in modo che il nostro test utilizzi il server di test sei libero di eseguire un https //github com/parse community/parse server locale per i tuoi test creeremo semplicemente un'altra applicazione back4app nel nostro dashboard se hai bisogno di un ripasso su come fornire un altro server back4app, vai al https //www back4app com/docs/get started/new parse app chiama la tua applicazione come vuoi, anche se potrebbe essere saggio usare qualcosa come testbackend poi prendi semplicemente l'id dell'applicazione e la chiave master da dashboard > impostazioni app > sicurezza e chiavi ora salva questi token nel nostro file di costanti in questo modo 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 } non inserire l'id dell'applicazione e la chiave master della tua app di produzione!!! stiamo per eliminare dati, e farlo comporterĂ il rischio di perdere dati 5\ utility di test le funzioni cloud vengono passate come parametri negli oggetti request e response di express il server crea automaticamente questi parametri quando vengono eseguiti nel cloud, quindi per i nostri ambienti di test dobbiamo creare dei doppi questo caso è piĂš semplice quando viene chiamata una funzione cloud, i dati vengono passati; nel nostro caso, vengono passati il profilo e le informazioni dell'utente ogni argomento fornito è accessibile dalla proprietĂ request params quindi, se chiamiamo una funzione cloud come 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 ); quindi la proprietĂ request params conterrĂ i dati passati 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 // } semplice, per i nostri test, quando chiamiamo la nostra funzione cloud il primo argomento dovrebbe essere della forma 1 { 2 params { 3 username 'testuser', 4 firstname "john", 5 // the rest of the arguments 6 } 7 } quindi non abbiamo bisogno di creare un oggetto mock speciale in questo caso l'oggetto di risposta consente al codice cloud di inviare una risposta http al client che rappresenta un successo o un fallimento vorremmo sapere come si chiama quando si invoca la funzione cloud di seguito è riportato un https //msdn microsoft com/en us/library/ff650441 aspx che permetterĂ al nostro test di determinare se l'invocazione è stata un successo o meno se questo è confuso, non preoccuparti, basta metterlo nel tuo file /spec/utils/response stub js 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; in breve, questa funzione costruttore javascript fornirĂ un modo per il nostro test di passare un oggetto di risposta che indica tramite risoluzione / rifiuto della promise se la funzione cloud avrebbe restituito un successo o un errore pulizia del database ovviamente non vogliamo che il nostro database parse di test mantenga ciò che si accumula durante un test definiamo un'utilitĂ per cancellare le tabelle del database, che può essere chiamata prima (o dopo) i casi di test aggiungi quanto segue a âspec/utils/purge parse table jsâ 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 } dopo aver definito questa funzione, è un buon momento per ricordarti di assicurarti che il tuo spec/utils/constants js sia configurato per la tua applicazione parse di test, non per la tua applicazione parse di produzione questo eliminerĂ i dati, quindi ti preghiamo di confermare che questo sia il database vuoto che hai creato sopra questa funzione accetta il nostro sdk parse configurato e restituisce un'altra funzione la funzione restituita accetta un nome di tabella e rimuove tutti i dati dalla corrispondente tabella parse ancora una volta, l'idea di restituire una funzione può sembrare strana, ma consente allo spec di test di configurare l'endpoint parse e poi fare riferimento a una funzione che cancellerĂ la tabella di quello endpoint parse fantastico! ora scriviamo il nostro test! 6\ testa che la cloud function invierĂ un errore se i parametri appropriati non vengono passati la cloud function si basa su determinati parametri inclusi e dovrebbe fallire se, ad esempio, il âfirstnameâ non è stato inviato assicuriamoci modificheremo il nostro file di test (finalmente!) spec/signup user spec js ecco cosa deve succedere prima delle definizioni del test importa il parse nodejs sdk importa le nostre costanti e configura il parse sdk per puntare al nostro server di test importa la nostra cloud function importa il nostro strumento âpurge tableâ importa l'oggetto response mock che abbiamo creato il seguente sarĂ sufficiente 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"); ora aggiungiamo i casi di test l' https //jasmine github io/2 1/introduction può aiutare a comprendere meglio la struttura, ma appare cosĂŹ (preso dall'introduzione) describe("a suite", () => { it("contains spec with an expectation", () => { expect(true) tobe(true); }); }); quindi i blocchi describe racchiudono suite di test, e i blocchi âitâ rappresentano casi e aspettative passando un parametro ai blocchi âitâ, puoi eseguire test in modo asincrono il test non verrĂ completato fino a quando il parametro non verrĂ invocato in questo modo it("non finirĂ fino a quando done non viene chiamato", (done) => { settimeout(() => { done(); }, 100); // 100 ms expect(x) tobe(y); }) questo è utile poichĂŠ uno dei nostri test utilizzerĂ http, quindi dovrebbe essere eseguito in modo asincrono in questo modo poichĂŠ l'uso di http è una procedura non bloccante in nodejs inoltre, jasmine consente blocchi speciali all'interno delle suite che possono essere eseguiti in diversi momenti del ciclo di vita del test vogliamo eliminare tutte le tabelle prima di ogni test, quindi eseguiremo il codice di purificazione nel blocco beforeeach basta parlare, aggiungiamo un po' di codice! inserisci il codice qui sotto nel tuo spec/signup user spec js, sotto le importazioni che abbiamo giĂ aggiunto 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 }); fantastico, il nostro primo test è andato a buon fine nel blocco beforeeach, purifichiamo le tabelle utente e profilo poi viene attivato il primo caso di test verifica che passare parametri non validi alla funzione signupuser faccia sĂŹ che la funzione invii un errore utilizza lo stub di risposta per assicurarsi che la funzione sia stata infine rifiutata poichĂŠ âsignupuserâ fallirĂ , il blocco âthenâ iniziale sullo stub non dovrebbe essere invocato se lo è, allora il nostro test fallisce! procedi e esegui il test utilizzando il seguente comando $ /node modules/jasmine/bin/jasmine js spec/signup user spec js dovresti vedere il seguente output randomizzato con seed 24618 iniziato 1 specifiche, 0 fallimenti finito in 1 376 secondi randomizzato con seed 24618 (jasmine random=true seed=24618) 7\ un test sulla persistenza dei dati spero che tu abbia un altro test in serbo! verificheremo che quando la nostra cloud function funziona correttamente, il nostro database sarĂ come previsto esisterĂ un profilo, con un riferimento a un oggetto utente, entrambi con gli attributi attesi aggiungi il seguente blocco al nostro esistente blocco âdescribeâ 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, questo è molto, quindi vediamo cosa succede instanziamo un oggetto mock di risposta, come nel primo caso di test poi eseguiamo signupuser con un doppio di richiesta contenente valid parametri, cosĂŹ come il mock di risposta (righe 6 16) successivamente, questo codice ascolta il metodo oncomplete dell'oggetto mock, che restituirĂ una promise la promise verrĂ rifiutata se viene chiamato response error, e risolta se viene chiamato response success qualsiasi rifiuto farĂ sĂŹ che la catena di promesse salti al blocco catch pertanto, il metodo fail è posizionato nel blocco catch, poichĂŠ il test dovrebbe fallire se la promise viene rifiutata la risposta della promise dovrebbe risolversi nell'oggetto profilo una volta risolta, eseguiremo una query per un profilo con lo stesso cognome che abbiamo creato (righe 19 21) poi il test conferma che il âfirstnameâ del profilo è lo stesso che abbiamo passato (righe 25 26) il blocco successivo recupera l'oggetto utente associato al profilo i puntatori degli oggetti parse vengono recuperati separatamente, da qui la necessitĂ di un altro blocco promise infine, il codice conferma che l'utente corrispondente ha il nome utente che è stato passato alla funzione signupuser poi il test termina vai avanti e esegui di nuovo il suite vai avanti e esegui il test utilizzando il seguente $ /node modules/jasmine/bin/jasmine js spec/signup user spec js dovresti vedere il seguente output randomizzato con seme 24618 iniziato 2 specifiche, 0 fallimenti finito in 2 876 secondi randomizzato con seme 24618 (jasmine random=true seed=24618) fantastico! abbiamo scritto del codice cloud e integrato un framework di test conclusione se ti sei perso, o semplicemente vuoi il codice per questo esempio, vai al https //github com/back4app/template cloud code unit test segui le istruzioni per scaricare ed eseguire se qualcosa non è chiaro, o non funziona, ti prego di contattarmi via gmail, jackconsidine3 spero che ti sia piaciuto questo tutorial e che tu abbia acquisito qualche intuizione!