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.
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.
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
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:
tekst
.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)))
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 ()))
findById
methode. Als er geen taak met die ID wordt gevonden, 404 fout is verzonden.Voer het testcommando nogmaals uit en het zou moeten slagen.
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:
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
.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.
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.