Een Node.js-API testen

Invoering

Testen zijn belangrijk; ze bieden een beveiliging voor uw toepassingen of API's. Als beginneling is het mogelijk dat u zich niet bewust bent van de noodzaak om tests te schrijven die de belangrijke onderdelen van uw gebouw bestrijken. Maar je zult het wel tegenkomen als je als ontwikkelaar vooruitgaat.

In een vorige zelfstudie, heb je geleerd hoe je een API bouwt met Node.js. Als je dit nog niet hebt gedaan, raad ik je aan dit te doen voordat je hiermee doorgaat. In deze zelfstudie schrijf je tests voor een API die is gebouwd met Node.js en Express. Aan het einde van deze zelfstudie weet u hoe testen in Node.js werkt en kunt u functionele en geteste API's bouwen.

Testhulpmiddelen

U maakt gebruik van Mocha, Expect en Supertest.

Mocha is een JavaScript-testraamwerk dat asynchrone tests eenvoudig en leuk maakt. Mocha wordt geleverd met tal van geweldige functies die te vinden zijn op de website. U zult een handvol van hen gebruiken.

Verwachten is een assertiebibliotheek die het voor u gemakkelijk maakt om betere beweringen te doen. Je zult zien hoe dat werkt. Supertest biedt een abstractie op hoog niveau voor het testen van HTTP. Dit is nodig omdat je een API gaat testen.

Genoeg gepraat, tijd om wat code te schrijven.

Project Setup

Ik heb een takenlijst-project dat al voor je is opgezet. Het model, het configuratiebestand en een deel van de app.js zijn al voor u klaar. Ga naar GitHub en kloon de repository. Of u kunt gewoon doen:

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

Uw package.json zou er als volgt uit moeten zien.

# package.json "name": "node-todo-api", "version": "1.0.0", "description": "", "main": "server.js", "scripts": " start ":" node server / server.js "," test ":" export NODE_ENV = test || SET \ "NODE_ENV = test \" && mocha server / ** / *. test.js "," test-watch " : "nodemon --exec 'npm test'", "engines": "node": "8.0.0", "keywords": [], "author": "", "license": "ISC" , "afhankelijkheden": "body-parser": "^ 1.17.2", "express": "^ 4.15.3", "lodash": "^ 4.17.4", "mongodb": "^ 2.2.29 "," mongoose ":" ^ 4.11.1 "," devDependencies ": " expect ":" ^ 1.20.2 "," mokka ":" ^ 3.4.2 "," nodemon ":" ^ 1.11.0 "," supertest ":" ^ 3.0.0 "

Voer nu de opdracht uit om de afhankelijkheden te installeren.

npm installeren

POST-aanvraagtest

Maak voor je test een nieuwe map met de naam test; deze map hoort in uw map te staan server directory. Maak nu een nieuw bestand waarin u uw test schrijft. Geef het bestand een naam server.test.js.

In dit bestand moet u beginnen met het vereisen van de modules die u hebt geïnstalleerd. U moet ook uw serverbestand en uw model nodig hebben.

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

U moet een paar taken hebben die tijdens tests worden gebruikt. Maar deze taken worden uit de testdatabase verwijderd telkens wanneer u uw testsuite uitvoert. Om dat te doen, maak twee tests zoals zo.

# server / test / server.test.js const todos = [_id: nieuwe ObjectId (), tekst: "Eerste test om", _id: nieuwe ObjectId (), tekst: "Tweede test om", voltooid: true , completedAt: 333] beforeEach ((done) => Todo.remove (). then (() => return Todo.insertMany (todos)). then (() => done ()) )

Het voorgaande blok maakt je Todo-database schoon en voegt de hierboven ingestelde taken in. Dit zorgt ervoor dat u een stabiel aantal vermeldingen in uw database hebt, zodat uw tests geen problemen opleveren.

Met dat gedaan, kunt u de test schrijven voor de POST verzoek. Voor jouw POST verzoek, zult u twee tests schrijven. De eerste zal een verzoek indienen voor een geldige taak en succesvol zijn. De tweede zal een aanvraag doen met een ongeldige instantie, en dit zou geen nieuwe taak moeten maken.

Hier is hoe de test eruit zou moeten zien.

# server / test / server.test.js beschrijven ('POST / todos', () => // 1 it ('zou een nieuwe taak moeten maken', (done) => let text = 'Test todo text' // 2 request (app) // 3 .post ('/ todos') .send (text) .expect (200) .expect ((res) => expect (res.body.text) .toBe ( tekst)) .end ((err, res) => // 4 if (err) return done (err) Todo.find (text). then ((todos) => // 5 expect (todos.length) .toBe (1) verwachten (todos [0] .text) .toBe (tekst) done ()). catch ((e) => done (e)))) it ('should geen todo maken met ongeldige body-gegevens ', (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)))))

Voer de test uit met behulp van de opdracht:

npm run test

Het zou moeten mislukken. Dit is wat er gebeurt:

  1. Beschrijft de test.
  2. Creëert een nieuwe taak en slaat deze op als een waarde voor tekst.
  3. U doet een POST-aanvraag aan de / todos pad van uw API, waarbij de taak die u hebt gemaakt, wordt verzonden als het hoofdgedeelte van het verzoek. U verwacht dat de statuscode voor het verzoek is 200 en het lichaam van de taak om de waarde van te evenaren tekst.
  4. Er is een fout geretourneerd als die er is en dit zal ertoe leiden dat het verzoek eindigt. Dus het volgende blok code zal niet worden uitgevoerd. Als er geen fout wordt aangetroffen, gaat de stroom verder.
  5. Er wordt een aanvraag ingediend bij de database om de gemaakte taak te vinden. U verwacht dat de lengte van de taken in de database 1 is en dat de tekst van de taak gelijk is aan de waarde van de tekst.
  6. Dit is de test die is gemaakt met ongeldige body-gegevens.
  7. EEN POST er wordt een verzoek ingediend bij de / todos pad. Deze keer stuur je een verzoek zonder lichaam. Je verwacht een te krijgen 400 verzoek. U hoeft het lichaam niet te controleren omdat u het niet verzendt. Als er een fout wordt aangetroffen, wordt deze geretourneerd en wordt de code gestopt.
  8. Als er geen fout wordt aangetroffen, wordt een aanvraag in de database gedaan om de lengte van de taken te controleren. We verwachten dat de database slechts 2 bevat, de to-dos die aan het begin zijn gemaakt.

Als u deze test wilt laten slagen, gaat u naar uw server.js bestand en drop in de code die nodig is voor de POST-aanvraag.

# 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)))

GET-aanvraagtest

Dit is eenvoudig: de test moet de lengte van de beschikbare doses in de database retourneren. Zoals je al weet, zou de lengte van de todos 2 moeten zijn. Waarom? Je raadde het goed. Aan het begin van de testsuite hebt u een gemaakt beforeEach block dat uw database opschoont en nieuwe taken invoegt telkens wanneer de testsuite wordt uitgevoerd.

Om te testen of het verzoek om alle taken goed te krijgen, is hier de code voor.

# server / test / server.test.js beschrijven ('GET / todos', () => it ('should all todos', (done) => request (app) .get ('/ todos') .expect (200) .expect ((res) => expect (res.body.todos.length) .toBe (2)) .end (done)))

In het bovenstaande maak je een KRIJGEN verzoek aan de / todos pad. Deze keer geef je niets door als het hoofdgedeelte van het verzoek, omdat het een is KRIJGEN verzoek. U verwacht een antwoord te ontvangen met de statuscode van 200. Dan verwacht je dat de lengte van de taken 2 zal zijn.

Wanneer u de test uitvoert, moet u een foutmelding krijgen. Probeer de fout zelf door te geven.

Ik wed dat je dat aan het werk hebt. Hier is de code om de test te laten slagen; vergelijk het met uw oplossing.

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

Wanneer een KRIJGEN er wordt een verzoek ingediend bij de / todos pad, je wilt elke taak in de Todo-verzameling vinden en ze teruggeven als taken. Dit toevoegen aan server.js zorgt ervoor dat de test slaagt.

Vervolgens schrijf je drie tests voor de KRIJGEN Verzoek gedaan om individuele taken op te halen. De eerste zou de taak moeten ophalen en teruggeven. De tweede en derde moeten terugkeren 404 fout in gevallen waarin de taak niet wordt gevonden.

Open je server.test.js en maak een nieuw beschrijvingsblok met de eerste testcase.

# server / server.test.js beschrijven ('GET / todos /: id', () => it ('moet todo doc retourneren', (done) => request (app) .get ('/ todos / $ todos [0] ._ id.toHexString () ') .expect (200) .expect ((res) => expect (res.body.todo.text) .toBe (todos [0] .text) ) .end (done))

Deze test maakt een KRIJGEN verzoek om de eerste taak op te halen die beschikbaar is in uw database. Je verwacht een te krijgen 200 statuscode en controleer vervolgens of de tekstwaarde van de taak identiek is aan de taak.

De volgende test ziet er als volgt uit.

 it ('moet 404 retourneren als todo niet wordt gevonden', (done) => let _id = nieuw ObjectId ('5967989ee978311656e93a59') request (app) .get ('/ todos / $ todos / _id.toHexString () ') .expect (404) .end (done))

Hier bent u op zoek naar een taak met een ID die niet overeenkomt met de ID van een taak die in uw database is opgeslagen. De test verwacht dat dit verzoek a retourneert 404 fout.

De laatste test is als de eerste, maar een beetje anders; hier is hoe het eruit ziet.

 it ('moet 404 retourneren voor niet-object-id's', (gereed) => laat hexId = '5967989ee978311656e93a5312' request (app) .get ('/ todos / $ todos / hexId') .expect (404). einde (klaar)))

Hier maakt u een ongeldig ObjectId en probeer de database te doorzoeken om een ​​taak te krijgen die overeenkomt met de ObjectId aangemaakt. De test verwacht dat het verzoek een a retourneert 404 fout. 

Wanneer u de test uitvoert, moeten ze allemaal mislukken. Voeg de onderstaande code toe aan uw account om ze te laten slagen server.js het dossier.

# 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 is niet geldig') Todo.findById (id) .then ((todo) => if (! Todo) // 3 return res.status (404) .send () res.send (todo) // 4) catch ((e) => res.status (400) .send ()))
  1. Haal de ID van de te doen taak op uit de params.
  2. Controleer om te zien of de ID geldig is. Als de ID niet geldig is, wordt een foutmelding verzonden waarin dit wordt vermeld.
  3. Als de ID geldig is, probeer dan een taak te vinden die overeenkomt met die ID met behulp van de findById methode. Als er geen taak met die ID wordt gevonden, 404 fout is verzonden.
  4. Als een taak wordt gevonden, wordt de taak verzonden. Vervolgens krijg je een fout die optreedt en verzendt deze.

Voer het testcommando nogmaals uit en het zou moeten slagen.

VERWIJDER verzoekstest

De test voor jouw DELETE verzoek zal een beetje lijken op wat je hebt voor je GET-verzoek.

Ten eerste wilt u testen of een taak is verwijderd.

# server / test / server.test.js beschrijven ('DELETE / todos /: id', () => it ('should go a todo', (done) => let hexId = todos [0] ._ id .toHexString () // 1 request (app) .delete ('/ todos / $ hexId') .expect (200) .expect ((res) => expect (res.body.todo._id) .toBe (hexId)) .end ((err, res) => // 2 if (err) return done (err)) Todo.findById (hexId) .then ((todo) => // 3 verwachten (todo.hexId) .toNotExist () done ()). catch ((e) => done (e)))

Dit is wat er hierboven gebeurt:

  1. U stelt de id van de taak in op een variabele met de naam hexid. Vervolgens a DELETE er wordt een verzoek ingediend bij het pad van de taak, met behulp van de ID. Je verwacht een te krijgen 200 reactie en de taak die is behaald om overeen te komen met de waarde van hexid.
  2. Als een fout wordt aangetroffen, wordt deze geretourneerd.
  3. Als er geen fout is, gaat de test verder met het doorzoeken van uw database met behulp van de ID die is opgeslagen als de waarde van hexid. Sinds een DELETE aanvraag is eerder verzonden, verwacht de test dat de taak-overeenkomende ID niet bestaat.

Vervolgens wilt u testen dat wanneer een verzoek wordt gedaan om een ​​taak te verwijderen die niet bestaat, het antwoord a bevat 404 fout. Het is belangrijk om dit te hebben, omdat het niet mogelijk is om een ​​taak twee keer te verwijderen. Hier is hoe de test hiervoor eruit zou moeten zien.

# server / test / server.test.js it ('zou 404 moeten retourneren als todo niet gevonden is', (done) => let hexId = new ObjectId (). toHexString () request (app) .delete ('/ todos / $ todos / hexId ') .expect (404) .end (done))

Hiermee wordt een ID gemaakt voor een taak die niet in de database bestaat. Dan een DELETE er wordt gevraagd om de taak te verwijderen. Er wordt verwacht dat de test a 404 fout omdat de taak niet bestaat.

U wilt dat testen a DELETE het gebruik van een ongeldige ID levert a op 404 fout, zoals zo.

# server / test / server.test.js it ('zou 404 moeten retourneren voor niet-object-id's', (gereed) => request (app) .delete ('/ todos / 123abc') .expect (404) .end (gedaan) ) )

Om de test te laten slagen, open je server.js en laat je dit vallen.

# 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 ()))

Voer de opdracht uit om te testen:

npm run test

En je testen zouden voorbij moeten gaan.

Conclusie

Op dit moment weet u nu hoe u een testsuite opzet bij het bouwen van een API met Node.js. U hebt Mocha, Expect en Supertest gebruikt om een ​​API te testen. Een voordeel van dit doen is dat je Postman niet altijd hoeft te ontslaan bij het bouwen van je API. Met uw test kunt u ontdekken wat er kapot is.

Houd er rekening mee dat JavaScript, voordat we afronden, een van de de facto talen van het werken op het web is geworden. Het is niet zonder zijn leercurven, en er zijn ook genoeg kaders en bibliotheken om je bezig te houden. Als u op zoek bent naar extra middelen om te studeren of om te gebruiken in uw werk, kijk dan wat we op Envato Market beschikbaar hebben.

Met behulp van wat je nu weet, ben je goed om de wereld van testen te verkennen.