Test d'une API Node.js

introduction

Les tests sont importants. ils fournissent une protection pour vos applications ou API. En tant que débutant, il est possible d’oublier la nécessité d’écrire des tests qui couvrent les parties importantes de ce que vous construisez. Pourtant, vous le rencontrerez au fur et à mesure que vous progresserez en tant que développeur..

Dans un précédent tutoriel, vous avez appris à créer une API avec Node.js. Si vous ne l’avez pas parcourue, je vous suggère de le faire avant de poursuivre. Dans ce tutoriel, vous allez écrire des tests pour une API construite avec Node.js et Express. À la fin de ce didacticiel, vous saurez comment fonctionnent les tests dans Node.js et pourrez créer des API fonctionnelles et testées..

Outils de test

Vous utiliserez Mocha, Expect et Supertest.

Moka est un framework de test JavaScript qui rend les tests asynchrones simples et amusants. Moka est livré avec des tonnes de fonctionnalités intéressantes qui peuvent être trouvées sur le site. Vous allez en utiliser une poignée.

Attendre est une bibliothèque d’affirmation qui vous permet de faire de meilleures assertions. Vous allez voir comment ça marche. Supertest fournit une abstraction de haut niveau pour tester HTTP. Cela est nécessaire car vous allez tester une API.

Assez parlé, le temps d'écrire du code.

Configuration du projet

J'ai déjà un projet de liste de tâches à faire pour vous. Le modèle, le fichier de configuration et une partie du fichier app.js sont déjà terminés pour vous. Allez sur GitHub et clonez le référentiel. Ou vous pouvez simplement faire:

clone de git https://github.com/izuchukwu1/node-todo-api.git

Votre package.json devrait ressembler à ceci.

# package.json "name": "node-todo-api", "version": "1.0.0", "description": "", "main": "server.js", "scripts": " start ":" noeud serveur / serveur.js "," test ":" exportation NODE_ENV = test || SET \ "NODE_ENV = test \" && serveur mocha / ** / *. test.js "," test-watch " : "nodemon --exec 'npm test" "," moteurs ": " noeud ":" 8.0.0 "," mots clés ": []," auteur ":" "," licence ":" ISC " , "dependencies": "body-parser": "^ 1.17.2", "express": "^ 4.15.3", "lodash": "^ 4.17.4", "mongodb": "^ 2.2.29 "," mangouste ":" ^ 4.11.1 "," devDependencies ": " expect ":" ^ 1.20.2 "," mocha ":" ^ 3.4.2 "," nodemon ":" ^ 1.11.0 "," supertest ":" ^ 3.0.0 "

Maintenant, lancez la commande pour installer les dépendances.

npm installer

Test de demande POST

Pour votre test, créez un nouveau dossier appelé tester; ce dossier devrait être dans votre serveur annuaire. Créez maintenant un nouveau fichier dans lequel vous écrirez votre test. Nommez le fichier server.test.js.

Dans ce fichier, commencez par demander les modules que vous avez installés. Vous devez également avoir besoin de votre fichier serveur et de votre modèle..

# server / test / server.test.js const expect = require ('expect') const demande = require ('supertest') const ObjectId = require ('mongodb') const app = require ('./… / serveur ') const Todo = require (' ./… / models / todo ')

Vous devez avoir quelques tâches à faire lors des tests. Mais ces tâches seront supprimées de la base de tests à chaque fois que vous exécuterez votre suite de tests. Pour gérer cela, créez deux tests comme.

# server / test / server.test.js const todos = [_id: nouvel ObjectId (), texte: "Premier test à faire", _id: nouvel ObjectId (), texte: "Deuxième test à exécuter", terminé: true , completedAt: 333] beforeEach ((done) => Todo.remove (). then (() => return Todo.insertMany (todos)). then (() => done ()) )

Le bloc before nettoie votre base de données Todo, puis insère le jeu de tâches à effectuer ci-dessus. Cela garantit que vous avez un nombre d'entrées stable dans votre base de données afin que vos tests ne rencontrent pas de problèmes..

Ceci fait, vous pouvez écrire le test pour le POSTER demande. Pour votre POSTER demande, vous allez écrire deux tests. Le premier demandera une tâche valide et réussira. Le second fera une demande avec un corps invalide, et cela ne devrait pas créer une nouvelle tâche à faire.

Voici à quoi devrait ressembler le test.

# server / test / server.test.js decrire ('POST / todos', () => // 1 it ('devrait creer un nouveau todo', (done) => let text = 'Test todo text' // 2 requête (app) // 3 .post ('/ todos') .send (text) .expect (200) .expect ((res) => expect (res.body.text) .toBe ( text)) .end ((err, res) => // 4 if (err) return done (err) à Todo.find (text). then ((todos) => // 5 expect (todos.length) .toBe (1) attend (todos [0] .text) .toBe (text) done ()). catch ((e) => done (e)))) il ('devrait ne crée pas de tâche avec des données de corps non valides ', (done) => // 6 request (app) // 7 .post (' / todos ') .send () .expect (400) .end ((err, res) => if (err) return done (err) Todo.find (). then ((todos) => // 8 expect (todos.length) .toBe (2) done ()). catch ((e) => done (e)))))

Exécutez le test à l'aide de la commande:

test d'exécution npm

Cela devrait échouer. Voici ce qui se passe:

  1. Décrit le test.
  2. Crée une nouvelle tâche et l’enregistre en tant que valeur de texte.
  3. Vous faites une demande POST au / todos chemin de votre API, en envoyant la tâche que vous avez créée comme corps de la demande. Vous vous attendez à ce que le code de statut de la demande soit 200 et le corps de la tâche à égaler la valeur de texte.
  4. Une erreur est renvoyée s'il y en a une, ce qui entraîne la fin de la demande. Ainsi, le prochain bloc de code ne fonctionnera pas. Si aucune erreur n'est rencontrée, le flux continue.
  5. Une demande est faite à la base de données pour trouver la tâche créée. Vous vous attendez à ce que la longueur des tâches dans la base de données soit égale à 1 et que le texte de la tâche soit égal à la valeur du texte.
  6. Ceci est le test effectué avec des données de corps non valides.
  7. UNE POSTER demande est faite à la / todos chemin. Cette fois, vous envoyez une demande sans corps. Vous vous attendez à obtenir un 400 demande. Pas besoin de vérifier le corps car vous n'en envoyez pas. Si une erreur est rencontrée, elle est renvoyée et le code cesse de s'exécuter..
  8. Si aucune erreur n'est rencontrée, une demande est faite à la base de données pour vérifier la longueur de la tâche. Nous nous attendons à ce que la base de données ne contienne que 2, qui sont les tâches à créer créées au début..

Pour réussir ce test, allez à votre server.js déposer et déposer le code nécessaire à la demande POST.

# server / server.js app.post ('/ todos', (req, res) => let todo = new Todo (text: req.body.text) todo.save (). then ((doc) => res.send (doc), (e) => res.status (400) .send (e)))

Demande de test GET

C’est simple: le test doit indiquer la longueur des tâches disponibles dans la base de données. Comme vous le savez déjà, la durée du todos devrait être de 2. Pourquoi? Vous avez bien deviné. Au début de la suite de tests, vous avez créé un avant chaque bloc qui nettoie votre base de données et insère de nouvelles tâches à faire chaque fois que la suite de tests est exécutée.

Pour tester que la demande d'obtenir toutes les tâches à faire, voici le code correspondant..

# server / test / server.test.js decrire ('GET / todos', () => it ('devrait avoir tous les todos', (done) => request (app) .get ('/ todos') .expect (200) .expect ((res) => expect (res.body.todos.length) .toBe (2)) .end (done)))

Dans ce qui précède, vous faites un OBTENIR demande au / todos chemin. Cette fois, vous ne transmettez rien en tant que corps de la demande car il s’agit d’une OBTENIR demande. Vous vous attendez à recevoir une réponse avec le code de statut de 200. Ensuite, vous vous attendez à ce que la durée des tâches soit de 2.

Lorsque vous exécutez le test, vous devriez obtenir une erreur. Essayez de vous tromper..

Je parie que vous avez ça pour travailler. Voici le code pour réussir le test; comparez-le avec votre solution.

# server / server.js app.get ('/ todos', (req, res) => Todo.find (). then ((todos) => res.send (todos), (e) => res.status (400) .send (e)))

Lorsqu'un OBTENIR demande est faite à la / todos chemin, vous voulez trouver toutes les tâches de la collection Todo et les renvoyer sous forme de tâches à faire. Ajouter ceci à server.js fait passer le test.

Ensuite, vous allez écrire trois tests pour le OBTENIR demande faite pour récupérer des tâches individuelles. Le premier doit récupérer et retourner la tâche à faire. Les deuxième et troisième devraient revenir 404 erreur dans les cas où la tâche n'est pas trouvée.

Ouvrez votre server.test.js et créer un nouveau bloc de description avec le premier cas de test.

# serveur / serveur.test.js décris ('GET / todos /: id', () => it ('doit retourner à do doc', (done) => request (app) .get ('/ todos / $ todos [0] ._ id.toHexString () ') .expect (200) .expect ((res) => expect (res.body.todo.text) .toBe (todos [0] .text) ) .end (terminé))

Ce test fait un OBTENIR demande de récupération de la première tâche disponible dans votre base de données. Vous vous attendez à obtenir un 200 code de statut, puis vérifiez que la valeur de texte de la tâche à faire est la même que celle créée.

Le prochain test ressemble à ceci.

 it ('devrait retourner 404 si todo n'est pas trouvé', (done) => let _id = new ObjectId ('5967989ee978311656e93a59') demande (app) .get ('/ todos / $ todos / _id.toHexString () ') .expect (404) .end (done))

Ici, vous recherchez une tâche à faire avec un identifiant qui ne correspond à l'identifiant d'aucune tâche enregistrée dans votre base de données. Le test s'attend à ce que cette demande renvoie un 404 Erreur.

Le dernier test est comme le premier mais un peu différent; voici à quoi ça ressemble.

 il ('devrait retourner 404 pour les identifiants non-objets', (done) => let hexId = '5967989ee978311656e93a5312' demande (app) .get ('/ todos / $ todos / hexId') .expect (404). fin (fait)))

Ici, vous créez un invalide ObjectId et essayez d'interroger la base de données pour obtenir une tâche correspondant à la ObjectId créé. Le test s'attend à ce que la demande renvoie un 404 Erreur. 

Lorsque vous exécutez le test, ils devraient tous échouer. Pour les faire passer, ajoutez le code ci-dessous à votre server.js fichier.

# server / server.js app.get ('/ todos /: id', (req, res) => let id = req.params.id // 1 if (! ObjectId.isValid (id)) // 2 return res.status (404) .send ('ID n'est pas valide') Todo.findById (id) .then ((todo) => if (! Todo) // 3 return res.status (404) .send () res.send (todo) // 4). catch ((e) => res.status (400) .send ()))
  1. Récupère l'ID de la tâche demandée par les params.
  2. Vérifiez si l'ID est valide. Si l'ID n'est pas valide, une erreur indiquant que cela est envoyé.
  3. Si l’ID est valide, essayez de trouver une tâche qui correspond à cet ID en utilisant le findById méthode. Si aucune tâche à faire n’est trouvée avec cet ID, un 404 l'erreur est envoyée.
  4. Si une tâche est trouvée, la tâche est envoyée. Alors vous attrapez n'importe quelle erreur qui se produit et l'envoyez.

Exécutez la commande de test une fois de plus, et il devrait passer.

DELETE Demande de test

Le test pour votre EFFACER demande sera un peu comme ce que vous avez pour votre demande GET.

Tout d'abord, vous voulez tester qu'une tâche est supprimée.

# server / test / server.test.js decrire ('DELETE / todos /: id', () => it ('devrait effacer une tâche', (done) => let hexId = todos [0] ._ id .toHexString () // 1 demande (app) .delete ('/ todos / $ hexId') .expect (200) .expect ((res) => expect (res.body.todo._id) .toBe (hexId)) .end ((err, res) => // 2 if (erreur) return done (erreur)) Todo.findById (hexId) .then ((todo) => // 3 expect (todo.hexId) .toNotExist () done ()). catch ((e) => done (e)))

Voici ce qui se passe ci-dessus:

  1. Vous définissez l'identifiant de la tâche à faire sur une variable appelée hexId. Ensuite, un EFFACER demande est faite sur le chemin de la tâche à faire, en utilisant l'ID. Vous vous attendez à obtenir un 200 réponse, et la tâche à accomplir pour correspondre à la valeur de hexId.
  2. Si une erreur est rencontrée, elle est renvoyée..
  3. En l'absence d'erreur, le test va plus loin pour interroger votre base de données en utilisant l'ID enregistré en tant que valeur de hexId. Depuis un EFFACER demande a déjà été envoyée, le test s'attend à ce que la tâche correspondant à cet ID n'existe pas.

Ensuite, vous voulez vérifier que lorsqu'une demande est faite pour supprimer une tâche qui n'existe pas, la réponse contient un 404 Erreur. Il est important de l’avoir, car il n’est pas possible de supprimer une tâche deux fois. Voici à quoi devrait ressembler le test..

# server / test / server.test.js it ('devrait retourner 404 si la tâche à faire n’est pas trouvée', (done) => let hexId = nouvel ObjectId (). toHexString () request (app) .delete ('/ todos / $ todos / hexId ') .expect (404) .end (done))

Cela crée un identifiant pour une tâche qui n'existe pas dans la base de données. Puis un EFFACER demande est faite pour supprimer la tâche à faire. Le test devrait renvoyer un 404 erreur car la tâche n'existe pas.

Vous voulez tester qu'un EFFACER l'utilisation d'un identifiant invalide renvoie un 404 erreur, comme si.

# server / test / server.test.js it ('devrait renvoyer 404 identifiants non-objets', (done) => request (app) .delete ('/ todos / 123abc') .expect (404) .end (terminé) ) )

Pour que le test réussisse, ouvrez votre server.js et déposez-le.

# server / server.js app.delete ('/ todos /: id', (req, res) => let id = req.params.id if (! ObjectId.isValid (id)) return res.status ( 404) .send () Todo.findByIdAndRemove (id) .then ((todo) => if (! Todo) return res.status (404) .send () res.send (todo)) .catch ((e) => res.status (400) .send ()))

Exécutez la commande pour tester:

test d'exécution npm

Et vos tests devraient passer.

Conclusion

À ce stade, vous savez maintenant comment configurer une suite de tests lors de la construction d'une API à l'aide de Node.js. Vous avez utilisé Mocha, Expect et Supertest pour tester une API. L'un des avantages de cette opération est que vous n'avez pas toujours besoin de lancer Postman lors de la construction de votre API. Avec votre test, vous pouvez savoir ce qui est cassé.

Avant de terminer, notez que JavaScript est devenu l'un des langages de facto du travail sur le Web. Ce n’est pas sans ses courbes d’apprentissage, et il existe de nombreux cadres et bibliothèques pour vous tenir occupé. Si vous recherchez des ressources supplémentaires à étudier ou à utiliser dans votre travail, consultez ce que nous avons à votre disposition sur le marché Envato..

En utilisant ce que vous savez maintenant, vous êtes bon pour explorer le monde des tests.