Testing av en Node.js API

Introduksjon

Tester er viktige; De gir en garanti for dine applikasjoner eller APIer. Som nybegynnere er det mulig å være uvitende om behovet for å skrive tester som dekker viktige deler av det du bygger. Likevel møter du det som du gjør fremgang som utvikler.

I en tidligere opplæring lærte du å bygge en API med Node.js. Hvis du ikke har gått gjennom det, foreslår jeg at du gjør det før du fortsetter med dette. I denne opplæringen vil du skrive tester for en API som er bygget med Node.js og Express. På slutten av denne opplæringen vil du vite hvordan testingen fungerer i Node.js, og du vil kunne bygge funksjonelle og testede APIer.

Testverktøy

Du vil benytte deg av Mokka, Forvent og Supertest.

Mocha er et JavaScript-testramme som gjør asynkron testing enkel og morsom. Mokka kommer med mange flotte funksjoner som finnes på nettsiden. Du vil gjøre bruk av en håndfull av dem.

forvent er et påstandsbibliotek som gjør det enkelt for deg å gjøre bedre påstander. Du vil se hvordan det fungerer. Supertest gir en abstraksjon på høyt nivå for å teste HTTP. Dette er nødvendig fordi du skal teste en API.

Nok snakk, tid til å skrive noen kode.

Prosjektoppsett

Jeg har et gjøremålsliste som allerede er satt opp for deg. Modellen, konfigurasjonsfilen og en del av app.js er allerede gjort for deg. Gå over til GitHub og klon depotet. Eller du kan bare gjøre:

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

Din package.json bør se slik ut.

# package.json "name": "node-todo-api", "versjon": "1.0.0", "beskrivelse": "", "main": "server.js", "scripts" start ":" node server / server.js "," test ":" eksport NODE_ENV = test || SET \ "NODE_ENV = test \" && mocha server / ** / *. test.js "," test-watch " : "node": "Nøkkelord": [], "Forfatter": "", "Lisens": "ISC" , "avhengigheter": "body-parser": "^ 1.17.2", "express": "^ 4.15.3", "lodash": "^ 4.17.4", "mongodb": "^ 2.2.29 "," mongoose ":" ^ 4.11.1 "," devDependencies ": " forvente ":" ^ 1.20.2 "," mocha ":" ^ 3.4.2 "," nodemon ":" ^ 1.11.0 "," supertest ":" ^ 3.0.0 "

Kjør nå kommandoen for å installere avhengighetene.

npm installasjon

POST-forespørselstest

For testen, opprett en ny mappe som heter test; denne mappen skal være i din serveren katalogen. Opprett nå en ny fil der du skal skrive testen din. Gi filen navnet server.test.js.

I denne filen starter du ved å kreve modulene du har installert. Du må også kreve serverfilen din og din modell.

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

Du må ha noen to-doser som skal brukes under testene. Men disse to-dos vil bli slettet fra testdatabasen hver gang du kjører testpakken. For å håndtere det, opprett to tester som dette.

# server / test / server.test.js const todos = [_id: new ObjectId (), tekst: "First test todo", _id: new ObjectId (), tekst: "Second test todo" , ferdigAt: 333] førEk ((ferdig) => Todo.remove (), deretter (() => retur Todo.insertMany (todos)) )

Tidligere blokk renser din Todo-database, og legger deretter inn to-dos-settet ovenfor. Dette sikrer at du har en stabil mengde oppføringer i databasen din, slik at testene dine ikke løser problemer.

Med det gjort kan du skrive testen for POST be om. For din POST forespørsel, vil du skrive to tester. Den første vil gjøre en forespørsel om gyldig gjøremål og bli vellykket. Den andre vil gjøre en forespørsel med en ugyldig kropp, og dette bør ikke skape en ny oppgave.

Her er hva testen skal se ut.

# server / test / server.test.js beskriver ('POST / todos', () => // 1 det ('skal opprette en ny todo', (done) => let text = 'Test todo text' // 2 forespørsel (app) // 3 .post ('/ todos') .send (text) .expect (200) .expect ((res) => expect (res.body.text) .toBe tekst)) .end ((err, res) => // 4 hvis (err) return ferdig (feil) Todo.find (text). deretter ((todos) => // 5 forvente (todos.length) .toBe (1) forvente (todos [0] .text) .toBe (tekst) gjort ()) catch ((e) => ferdig (e)))) ikke opprette todo med ugyldige kroppsdata ', (ferdig) => // 6 forespørsel (app) // 7 .post (' / todos ') .send () .expect (400) .end ( res) => hvis (feil) return done (err) Todo.find (). deretter ((todos) => // 8 forventer (todos.length) .toBe (2) done ()). fange ((e) => ferdig (e)))))

Kjør testen ved hjelp av kommandoen:

npm løp test

Det burde mislykkes. Her er hva som skjer:

  1. Beskriver testen.
  2. Oppretter en ny oppgave og lagrer den som en verdi for tekst.
  3. Du gjør en POST-forespørsel til / todos sti i API-en din, send den oppgavene du opprettet som forespørselen. Du forventer at statuskoden for forespørselen skal være 200 og kroppen til å gjøre til lik verdien av tekst.
  4. En feil returneres hvis det er noe, og dette vil føre til at forespørselen slutter. Således vil den neste koden ikke løpe. Hvis ingen feil oppstår, fortsetter strømmen.
  5. En forespørsel er gjort i databasen for å finne den opprettede oppgaven. Du forventer at lengden på to-dosen i databasen skal være 1, og teksten til oppgaven skal være lik verdien av teksten.
  6. Dette er testen laget med ugyldige kroppsdata.
  7. EN POST forespørsel er gjort til / todos sti. Denne gangen sender du en forespørsel uten kropp. Du forventer å få en 400 be om. Du trenger ikke å sjekke kroppen mens du ikke sender noen. Hvis det oppdages en feil, blir den returnert og koden slutter å løpe.
  8. Hvis det ikke oppdages en feil, blir det forespurt til databasen for å sjekke lengden på dosen. Vi forventer at databasen kun vil inneholde 2, som er den til-dosen som er opprettet i begynnelsen.

For å få denne testen forbi, gå til din server.js fil og slipp i koden som trengs for POST-forespørselen.

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

GET Request Test

Dette er enkelt - testen skal returnere lengden på dosen som er tilgjengelig i databasen. Som du allerede vet, bør lengden på todos være 2. Hvorfor? Du gjettet riktig. I begynnelsen av testpakken skapte du en beforeEach blokkere det som renser databasen din og legger inn ny til-dos hver gang testpakken kjøres.

For å teste at forespørselen om å få alt til dos fungerer, her er koden for det.

# server / test / server.test.js beskriver ('GET / todos', () => det ('skal få alle todos', (done) => request (app) .get ('/ todos') .expect (200) .expect ((res) => expect (res.body.todos.length) .toBe (2)) .end (ferdig)))

I det ovennevnte gjør du en forespørsel til / todos sti. Denne gangen passerer du ikke noe som formen av forespørselen fordi det er a be om. Du forventer å få svar med statuskoden til 200. Da forventer du at lengden på dosen vil være 2.

Når du kjører testen, bør du få en feil. Prøv å få feilen til å passere på egen hånd.

Jeg vedder på at du fikk det til å fungere. Her er koden for å få testen til å passere; sammenlign det med løsningen din.

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

Når en forespørsel er gjort til / todos sti, du vil finne alt du trenger i Todo samlingen og returnere dem som til-dos. Legger til dette til server.js får testen til å passere.

Deretter skal du skrive tre tester for forespørsel om å hente individuelle til-doser. Den første skal hente og returnere oppgaven. Den andre og tredje skal returnere 404 feil i tilfeller der oppgaven ikke er funnet.

Åpne opp din server.test.js og opprett en ny beskrivningsblokk med det første testet.

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

Denne testen gjør en Be om å hente den første oppgaven som er tilgjengelig i databasen din. Du forventer å få en 200 statuskode, og kontroller at tekstverdien til oppgaven er den samme som den som ble opprettet.

Neste test ser slik ut.

 den ('skal returnere 404 hvis todo ikke er funnet', (ferdig) => let _id = new ObjectId ('5967989ee978311656e93a59') forespørsel (app) .get ('/ todos / $ todos / _id.toHexString () ') .expect (404) .end (ferdig))

Her ser du etter en gjøremål som bruker en ID som ikke samsvarer med ID-en til gjøremål som er lagret i databasen. Testen forventer at denne forespørselen returnerer a 404 feil.

Den siste testen er som den første, men litt annerledes; her er hvordan det ser ut.

 det ('skal returnere 404 for ikke-objekt-ID', (gjort) => la hexId = '5967989ee978311656e93a5312' forespørsel (app) .get ('/ todos / $ todos / hexId') .expect (404). slutt (ferdig)))

Her oppretter du en ugyldig Objekt og prøv å spørre databasen for å få en oppgave som passer til Objekt opprettet. Testen forventer at anmodningen om å returnere a 404 feil. 

Når du kjører testen, burde de alle mislykkes. For å få dem til å passere, legg koden under til din server.js fil.

# server / server.js app.get ('/ todos /: id', (req, res) => la id = req.params.id // 1 hvis (! ObjectId.isValid (id)) // 2 returnere res.status (404) .send ('ID er ikke gyldig') Todo.findById (id) .then ((todo) => if (! Todo) // 3 return res.status (404) .send () res.send (todo // // .fang ((e) => res.status (400) .send ()))
  1. Få IDen til oppgavespørsmålet fra parametrene.
  2. Sjekk om IDen er gyldig. Hvis ID-en ikke er gyldig, sendes en feil som angir dette.
  3. Hvis ID-en er gyldig, prøv å finne en oppgave som samsvarer med denne ID-en ved hjelp av findById metode. Hvis det ikke finnes noe å gjøre med den ID-en, a 404 feilen er sendt.
  4. Hvis en oppgave er funnet, sendes oppgaven. Deretter tar du noen feil som oppstår og sender den.

Kjør testkommandoen en gang til, og den skal passere.

DELETE forespørselstest

Testen for din SLETT forespørsel vil være litt som hva du har for din GET-forespørsel.

Først vil du teste at en å gjøre er slettet.

# server / test / server.test.js beskriver ('DELETE / todos /: id', () => det ('skal slette en todo', (ferdig) => la hexId = todos [0] ._ id .toHexString () // 1 forespørsel (app) .delete ('/ todos / $ hexId') .expect (200) .expect ((res) => expect (res.body.todo._id) .toBe (heksId)) .end ((err, res) => // 2 hvis (err) retur gjort (err)) Todo.findById (hexId) .then ((todo) => // 3 forventer (todo.hexId) .toNotExist () ferdig ()) .fangst ((e) => ferdig (e)))

Her er hva som skjer over:

  1. Du angir iden til oppgaven til en variabel som heter hexId. Deretter a SLETT Forespørsel er gjort på banen til gjengen, ved hjelp av ID. Du forventer å få en 200 svar, og oppgaven oppnådd for å matche verdien av hexId.
  2. Hvis det oppdages en feil, returneres den.
  3. Hvis det ikke er noe feil, går testen videre for å spørre databasen din ved hjelp av IDen som er lagret som verdien av hexId. Siden a SLETT Forespørsel er tidligere sendt, forventer testen at oppgaven som samsvarer med den IDen ikke eksisterer.

Deretter vil du teste at når en forespørsel blir gjort om å slette en oppgave som ikke eksisterer, inneholder svaret a 404 feil. Det er viktig å ha dette, da det ikke er mulig å slette en oppgave to ganger. Her er hvordan testen for dette skal se ut.

# server / test / server.test.js det ('skal returnere 404 hvis todo ikke er funnet', (ferdig) => la hexId = ny ObjectId (). toHexString () forespørsel (app) .delete ('/ todos / $ todos / hexId ') .expect (404) .end (ferdig))

Dette skaper en ID for en gjøremål som ikke finnes i databasen. Deretter en SLETT Forespørsel er gjort for å slette oppgaven. Testen forventes å returnere a 404 Feil da oppgaven ikke eksisterer.

Du vil teste det a SLETT bruker en ugyldig ID returnerer a 404 Feil, slik.

# server / test / server.test.js det ('skal returnere 404 for ikke-objekt ids', (ferdig) => forespørsel (app) .delete ('/ todos / 123abc') .expect (404) .end (ferdig)))

For å få testen til å passere, åpne server.js og slipp dette.

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

Kjør kommandoen for å teste:

npm løp test

Og dine tester skal passere.

Konklusjon

På dette punktet vet du nå hvordan du konfigurerer en testpakke når du bygger en API ved hjelp av Node.js. Du har brukt Mocha, Expect og Supertest til å teste en API. En fordel ved å gjøre dette er at du ikke alltid trenger å skyte opp Postman når du bygger din API. Med testen kan du bli kjent med det som er ødelagt.

Før vi pakker opp, merk at JavaScript har blitt et av de de facto språkene som fungerer på nettet. Det er ikke uten sine lærekurver, og det er nok av rammer og biblioteker for å holde deg opptatt også. Hvis du leter etter flere ressurser for å studere eller bruke i arbeidet ditt, sjekk ut hva vi har tilgjengelig på Envato Market.

Ved å bruke det du nå vet, er du god til å utforske testningsverdenen.