Advanced Guides
Intégration des tests automatisés avec Parse Cloud Code
37 min
comment intégrer des tests dans vos fonctions de code cloud parse introduction ceci est un guide écrit par https //github com/considine , notre écrivain invité et développeur principal chez https //koptional com/ le tutoriel couvre comment configurer des tests automatisés pour votre code cloud back4app nous parlerons brièvement de la façon de déplacer une partie de votre code client parse vers le cloud, puis de la manière d'intégrer votre projet dans un écosystème de test vous pouvez également consulter le projet exemple https //github com/back4app/template cloud code unit test directement pour une version fonctionnelle objectifs nous espérons combiner les aspects robustes et évolutifs des tests automatisés avec l'environnement parse convivial pour les développeurs en tirant parti de cloud code, peut être une fonctionnalité sous estimée de parse, les développeurs peuvent continuer à itérer rapidement leur code et être confiants que le logiciel fonctionnera comme prévu développement piloté par les tests https //en wikipedia org/wiki/test driven development est un domaine immense ; plutôt que de parler philosophiquement des tests, nous allons passer en revue une mise en œuvre et discuter de certaines stratégies (comme le stubbing par exemple) prérequis pour compléter ce tutoriel, vous avez besoin de une application sur back4app suivez le tutoriel créer une nouvelle application pour apprendre à créer une application sur back4app back4app command line configuré avec le projet suivez le tutoriel configurer cloud code pour apprendre à configurer le code cloud pour un projet npm installé sur votre ligne de commande remarque cette bibliothèque utilisera le https //www promisejs org/ , ce qui ne devrait pas être trop compliqué créons un backend de réseau social basique d'accord ! imaginez une application de réseau social qui inclut un modèle de profil en plus du modèle d'utilisateur pour certaines applications, vous pouvez placer les informations de profil dans le modèle d'utilisateur, bien que dans de nombreux cas, cela ne soit pas efficace ; vous aurez souvent besoin de séparer les préoccupations d'autorisation/authentification du contenu utilisateur, et donc de maintenir deux modèles différents dans ce tutoriel, nous allons mettre en œuvre une fonctionnalité qui gère la création d'utilisateurs et de profils de cette manière, en exerçant une pression minimale sur le client commençons ! 1\ définir nos fonctions cela suppose que vous avez un projet back4app créé et que l'outil en ligne de commande est installé (voir les prérequis) pour des exemples de code frontend, ce guide fera référence à la syntaxe du sdk javascript parse pour plus de simplicité lorsque quelqu'un s'inscrit à cette application, un profil doit être créé et associé à l'objet utilisateur la fonction d'inscription dans de nombreuses applications parse, vous créerez l'utilisateur avec la syntaxe suivante 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"); dans notre cas, nous aimerions également initialiser un profil et le lier à l'objet utilisateur 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 }) vous pourriez raccourcir cette syntaxe pour qu'elle ressemble à ceci 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 }) malheureusement, cela implique toujours de faire deux requêtes séparées au serveur parse, ce qui est inefficace pour un frontend ; il est sage d'éviter les flux de communication client serveur en plusieurs étapes lorsque cela est possible de plus, en ce qui concerne la sécurité, le code ci dessus confie le processus de création à un client, ce qui n'est jamais judicieux nous aimerions éviter que l'intégrité de nos données dépende d'un client complétant correctement toutes les étapes d'un flux ils pourraient, par exemple, envoyer une requête personnalisée qui crée un utilisateur sans profil, corrompant les données persistantes de l'application pourquoi ne pas tout faire en une seule étape en utilisant le code cloud ? cela peut éviter le gonflement du code frontend et garantir que le client ne fait pas de travail inutile/insecure ! voici ce que nous voulons faire à la place du client pour l'inscription 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 définit également pour http //docs parseplatform org/cloudcode/guide/#beforesave triggers des déclencheurs, permettant la création du profil lorsque l'utilisateur s'inscrit cependant, en utilisant une fonction, nous pouvons intuitivement passer les attributs firstname et lastname que le profil utilisera fonction d'inscription de code cloud commençons ! déplacez vous vers votre répertoire de projet qui est synchronisé avec back4app (voir les prérequis si vous ne savez pas ce que cela signifie) nous allons supposer la structure suivante dans notre cas, lors de l'initialisation, nous avons choisi ‘cloud’ comme nom de répertoire votre répertoire peut être appelé comme vous le souhaitez 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 }); vous remarquerez peut être que l'option ‘usemasterkey’ est passée ; cela permet au code cloud de supplanter tous les rôles ou acl qui pourraient être en place étant donné que le client ne touche pas à ce code, il n'y a aucun risque qu'il détourne notre serveur cependant, veuillez faire attention avec ce drapeau ! dans le cas où il n'est pas évident pourquoi cela pourrait être préférable de placer cette fonctionnalité dans le code client, voici quelques avantages décharge le calcul sur le serveur plutôt que sur l'appareil définit explicitement la fonctionnalité d'un processus plus facile de créer des fonctions à l'épreuve des pannes donne au client une interface intuitive cela empêche la possibilité qu'un client 'fasse à moitié' un processus 2\ refactoriser notre structure de répertoire super, nous avons créé deux fonctions cloud nous pourrions évidemment tester ces fonctions en les exécutant et en vérifiant le tableau de bord parse, mais ce n'est pas évolutif ni efficace nous voulons plutôt créer des tests automatisés spécifiquement pour les méthodes qui peuvent être exécutées en continu nous allons donc séparer un peu notre code nous allons déplacer les fonctions que nous avons créées dans main js vers un nouveau fichier appelé cloud functions js (dans le même répertoire) ensuite, nous allons importer ces fonctions dans main, et les lier aux définitions de fonctions cloud l'idée est de découpler les fonctions de l'interface cloud afin que nous puissions les tester sans envoyer de requêtes http de manière inefficace cela aura beaucoup de sens lorsque nous créerons la suite de tests créer le fichier de fonctions vous êtes peut être conscient que vous pouvez utiliser 'require' dans node js pour importer des fonctions, des objets et des variables d'autres fichiers nous allons donc définir des fonctions correspondant à la fonction cloud parse que nous avons créée à l'étape 1 un point potentiellement déroutant est que les fonctions que nous définissons seront des fonctions de retour , qui peuvent ensuite être intégrées dans la définition de parse cloud il peut sembler étrange d'utiliser une fonction pour retourner une fonction, mais cela nous donnera le pouvoir de remplacer les serveurs parse plus tard lorsque nous écrirons nos tests vous avez peut être remarqué que vous pouvez utiliser l'objet parse dans votre code cloud, sans jamais avoir à le définir ou à l'importer cela est dû au serveur qui exécute ce code ajoutant parse automatiquement cependant, si nous voulons exécuter des tests sur les fonctions localement, nous n'avons pas accès à une instance en fait, nous aimerions fournir notre propre instance qui correspond à un serveur parse de test, où il n'y a aucun risque que des données soient créées ou supprimées chaque fonction acceptera ‘parse’ comme paramètre et renverra les fonctions 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 } dans main js, supprimez tout ce qui précède importez la fonction cloud et liez la fonction à la définition de la fonction cloud comme ceci 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)); super ! nous n'avons pas changé la fonctionnalité depuis l'étape 1, mais nous avons découplé la fonction du code cloud dans la prochaine étape, nous allons créer un test unitaire ! 3\ créer la suite de tests pour notre suite de tests, nous allons utiliser jasmine https //jasmine github io/ , le framework de test populaire cependant, notre code jusqu'à présent est complètement agnostique de nos tests, donc vous pouvez utiliser n'importe quel framework ou plateforme que vous préférez installons jasmine et jasmine node (une intégration de jasmine et de notre environnement node js) maintenant, installons deux bibliothèques que notre suite de tests utilisera elle utilisera le sdk parse pour se connecter à un faux serveur parse, et la bibliothèque events pour simuler l'objet de requête maintenant, en utilisant l'utilitaire jasmine, initialisons notre répertoire de tests si vous préférez, vous pouvez installer jasmine globalement avec $ npm install g jasmine $ npm install g jasmine , puis vous pouvez initialiser avec ceci $ jasmine init $ jasmine init ce guide supposera que vous n'installez pas jasmine globalement, bien que cela soit recommandé si vous le faites, vous pouvez remplacer toutes les instances de ‘/node modules/jasmine/bin/jasmine js’ par simplement ‘jasmine’ cela devrait créer un répertoire appelé spec, qui inclut lui même un dossier de support contenant des informations de configuration pour jasmine par défaut, jasmine sait chercher des fichiers qui se terminent par l'extension “ spec js”, donc nous nommerons nos tests en conséquence créez le fichier pour notre premier test unitaire ajoutez un répertoire utilitaires avec deux fichiers qui aideront avec nos tests enfin, créez un fichier constants dans le même répertoire l'utilité de ce fichier sera expliquée plus tard voici à quoi devrait ressembler votre répertoire maintenant 4\ échanger avec un serveur parse de test tester autour de parse puisque nos méthodes impliquent un serveur parse, nous voulons pouvoir tester cette interaction il y a deux façons de le faire a nous pouvons "stub" l'objet parse sdk, en définissant un objet qui implémente la même interface ensuite, il suffit de passer cet objet comme paramètre à nos méthodes cloud cela pourrait ressembler à quelque chose comme ceci 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 une autre approche consiste à configurer un vrai serveur parse qui servira uniquement pour les données de test cela impliquera la couche http lente que parse utilise, mais permettra également de tester les données dans la base de données dans nos tests, nous devrions importer le sdk parse et le configurer avec un serveur de test les deux endroits qui peuvent être stubés lors des tests de code cloud a ) stub un sdk parse qui ne fera pas de requêtes http, ou b ) échanger avec une implémentation de base de données de test aucune de ces approches n'est la "bonne" réponse cela dépend de ce que vous essayez de tester stub l'interface pour le sdk parse (même juste les parties que nous utilisons) est beaucoup de travail de plus, nous allons tester la persistance des données après enregistrement dans cet exemple, donc nous allons utiliser la deuxième approche allons y créer un serveur parse de test sur back4app récupérer l'id d'application et la clé maître et les enregistrer dans notre fichier de constantes initialiser le sdk parse dans notre fichier de spécifications, afin que notre test utilise le serveur de test vous êtes libre d'exécuter un serveur parse https //github com/parse community/parse server local pour vos tests nous allons simplement créer une autre application back4app dans notre tableau de bord si vous avez besoin d'un rappel sur la façon de provisionner un autre serveur back4app, rendez vous sur le tutoriel créer une nouvelle application https //www back4app com/docs/get started/new parse app appelez votre application comme vous le souhaitez, bien qu'il puisse être judicieux d'utiliser quelque chose comme testbackend ensuite, récupérez simplement l'id d'application et la clé maître dans tableau de bord > paramètres de l'application > sécurité & clés maintenant, enregistrez ces jetons dans notre fichier de constantes comme ceci 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 } ne mettez pas l'identifiant d'application et la clé maître de votre application de production !!! nous allons supprimer des données, et ce faisant, vous risquez de perdre des données 5\ outils de test les fonctions cloud sont passées en tant que paramètres dans les objets request et response d'express le serveur crée automatiquement ces paramètres lorsqu'ils sont exécutés dans le cloud, donc pour nos environnements de test, nous devons créer des doubles ce cas est plus facile lorsqu'une fonction cloud est appelée, des données sont passées ; dans notre cas, le profil et les informations utilisateur sont passés chaque argument fourni est accessible à partir de la propriété request params donc, si nous appelons une fonction cloud comme 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 ); alors la propriété request params contiendra les données passées 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 // } assez simple, pour nos tests, lors de l'appel de notre fonction cloud, le premier argument doit être sous la forme 1 { 2 params { 3 username 'testuser', 4 firstname "john", 5 // the rest of the arguments 6 } 7 } ainsi, nous n'avons pas besoin de créer un objet mock spécial dans ce cas l'objet de réponse permet au code cloud d'envoyer une réponse http au client représentant soit un succès, soit un échec nous aimerions savoir comment cela s'appelle lors de l'invocation de la fonction cloud ci dessous se trouve un objet fictif https //msdn microsoft com/en us/library/ff650441 aspx qui permettra à notre test de déterminer si l'invocation a été réussie ou non si cela est déroutant, ne vous inquiétez pas, placez le simplement dans votre fichier /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; en résumé, cette fonction constructeur javascript fournira un moyen pour notre test de passer un objet de réponse qui indique par la résolution / le rejet de la promesse si la fonction cloud aurait renvoyé un succès ou une erreur nettoyage de la base de données nous ne voulons évidemment pas que notre base de données parse de test conserve ce qui est accumulé pendant un test définissons une utilité pour effacer les tables de la base de données, qui peut être appelée avant (ou après) les cas de test ajoutez ce qui suit à ‘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 } après avoir défini cette fonction, il est bon de vous rappeler de vous assurer que votre spec/utils/constants js est configuré pour votre application parse de test, pas votre application parse de production cela supprimera des données, alors veuillez confirmer qu'il s'agit de la base de données vide que vous avez créée ci dessus cette fonction accepte notre sdk parse configuré et renvoie une autre fonction la fonction renvoyée accepte un nom de table et supprime toutes les données de la table parse correspondante encore une fois, l'idée de renvoyer une fonction peut sembler étrange, mais cela permet à la spécification du test de configurer le point de terminaison parse, puis de référencer une fonction qui effacera la table de ce point de terminaison parse génial ! maintenant, écrivons notre test ! 6\ testez que la fonction cloud enverra une erreur si les paramètres appropriés ne sont pas passés la fonction cloud repose sur certains paramètres devant être inclus et devrait échouer si, par exemple, le ‘firstname’ n'était pas envoyé assurons nous nous allons éditer notre fichier de test (enfin !) spec/signup user spec js voici ce qui doit se passer avant les définitions de test importer le sdk nodejs de parse importer nos constantes et configurer le sdk parse pour pointer vers notre serveur de test importer notre fonction cloud importer notre utilitaire “purge table” importer l'objet de simulation de réponse que nous avons créé ce qui suit suffira 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"); ajoutons maintenant les cas de test l' introduction à jasmine https //jasmine github io/2 1/introduction peut aider à mieux comprendre la structure, mais cela ressemble à ceci (tiré de l'intro) les blocs describe encapsulent les suites de tests, et les blocs ‘it’ représentent des cas et des attentes en passant un paramètre aux blocs ‘it’, vous pouvez exécuter des tests de manière asynchrone le test ne sera pas terminé tant que le paramètre n'est pas invoqué comme ceci c'est utile car l'un de nos tests utilisera http, donc il doit être exécuté de manière asynchrone de cette manière, car l'utilisation de http est une procédure non bloquante dans nodejs de plus, jasmine permet des blocs spéciaux au sein des suites qui peuvent s'exécuter à différents moments du cycle de vie des tests nous voulons supprimer toutes les tables avant chaque test, donc nous allons exécuter le code de purge dans le bloc beforeeach assez parlé, ajoutons du code ! placez le code ci dessous dans votre spec/signup user spec js, sous les imports que nous avons déjà ajoutés 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 }); génial, notre premier test est réussi dans le bloc beforeeach, nous purgons les tables user et profile ensuite, le premier cas de test est déclenché il vérifie que le passage de paramètres invalides à la fonction signupuser entraîne l'envoi d'une erreur par la fonction il utilise le stub de réponse pour s'assurer que la fonction a finalement été rejetée parce que ‘signupuser’ échouera, le bloc ‘then’ initial sur le stub ne devrait pas être invoqué s'il l'est, alors notre test échoue ! allez y et exécutez le test en utilisant ce qui suit vous devriez voir la sortie suivante 7\ un test sur la persistance des données j'espère que vous avez un test de plus en vous ! nous allons vérifier que lorsque notre fonction cloud fonctionne correctement, notre base de données sera conforme aux attentes un profil existera, avec une référence à un objet utilisateur, tous deux avec les attributs attendus ajoutez le bloc suivant à notre bloc de suite ‘décrire’ existant 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 }); d'accord, c'est beaucoup, alors passons en revue ce qui se passe nous instancions un objet de simulation de réponse, comme dans le premier cas de test ensuite, nous exécutons signupuser avec un double de requête contenant des paramètres valides, ainsi que la simulation de réponse (lignes 6 16) ensuite, ce code écoute la méthode oncomplete de l'objet simulé, qui renverra une promesse la promesse sera rejetée si un response error a été appelé, et résolue si un response success a été appelé tout rejet fera sauter la chaîne de promesses vers le bloc catch par conséquent, la méthode fail est placée dans le bloc catch, car le test doit échouer si la promesse est rejetée la réponse de la promesse devrait se résoudre en l'objet profil une fois qu'elle est résolue, nous interrogerons pour un profil ayant le même nom de famille que celui que nous avons créé (lignes 19 21) ensuite, le test confirme que le ‘firstname’ du profil est le même que celui que nous avons passé (lignes 25 26) le bloc suivant récupère l'objet utilisateur associé au profil les pointeurs d'objet parse se récupèrent séparément, d'où la nécessité d'un autre bloc de promesse enfin, le code confirme que l'utilisateur correspondant a le nom d'utilisateur qui a été passé à la fonction signupuser ensuite, le test se termine allez y et exécutez la suite une fois de plus allez y et exécutez le test en utilisant ce qui suit vous devriez voir la sortie suivante génial ! nous avons écrit du code cloud et intégré un cadre de test conclusion si vous vous êtes perdu, ou si vous voulez simplement le code pour cet exemple, rendez vous sur le dépôt github https //github com/back4app/template cloud code unit test suivez les instructions pour télécharger et exécuter si quelque chose n'est pas clair, ou ne fonctionne pas, veuillez me contacter via mon gmail, jackconsidine3 j'espère que vous avez apprécié ce tutoriel et que vous avez acquis des connaissances !