Testa ett Node.js API

Introduktion

Tester är viktiga; De ger skydd för dina applikationer eller API: er. Som nybörjare är det möjligt att vara omedveten om behovet av att skriva tester som täcker de viktiga delarna av det du bygger. Ändå kommer du att träffas med det som du gör framsteg som utvecklare.

I en tidigare handledning lärde du dig att bygga ett API med Node.js. Om du inte har gått igenom det, föreslår jag att du gör det innan du fortsätter med det här. I den här handledningen skrivs du tester för ett API byggt med Node.js och Express. I slutet av denna handledning kommer du att veta hur testningen fungerar i Node.js, och du kommer att kunna bygga funktionella och testade API: er.

Testverktyg

Du kommer att använda Mocha, Expect och Supertest.

Mocka är ett JavaScript-testramverk som gör asynkron testning enkelt och roligt. Mocka kommer med massor av bra funktioner som finns på hemsidan. Du kommer att utnyttja en handfull av dem.

Förvänta är ett påståendebibliotek som gör det enkelt för dig att göra bättre påståenden. Du kommer att se hur det fungerar. Supertest ger en hög abstraktion för testning av HTTP. Detta är nödvändigt eftersom du kommer att testa ett API.

Nogsamtal, tid att skriva en kod.

Projektinställningar

Jag har ett to-do list-projekt som redan är upprättat för dig. Modellen, konfigurationsfilen och en del av app.js är redan gjorda för dig. Gå över till GitHub och klona förvaret. Eller du kan helt enkelt göra:

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

Din package.json ska se ut så här.

# paket.json "namn": "nod-todo-api", "version": "1.0.0", "beskrivning": "", "main": "server.js", "scripts" starta ":" nodserver / server.js "," test ":" export NODE_ENV = test || SET \ "NODE_ENV = test \" && mocha server / ** / *. test.js "," test-watch " : "nodemon - exec 'npm test" "," motorer ": " nod ":" 8.0.0 "," nyckelord ": []," författare ":" "," licens ":" ISC " , "beroenden": "body-parser": "^ 1.17.2", "express": "^ 4.15.3", "lodash": "^ 4.17.4", "mongodb": "^ 2.2.29 "," mongoose ":" ^ 4.11.1 "," devDependencies ": " förvänta ":" ^ 1.20.2 "," mocha ":" ^ 3.4.2 "," nodemon ":" ^ 1.11.0 "," supertest ":" ^ 3.0.0 "

Kör nu kommandot för att installera beroenden.

npm installera

POST Request Test

För ditt test, skapa en ny mapp som heter testa; den här mappen ska vara i din server katalogen. Skapa nu en ny fil där du ska skriva ditt test. Namnge filen server.test.js.

I den här filen börjar du med att kräva modulerna du installerade. Du måste också kräva din serverfil och din modell.

const. = test / server ') const Todo = kräver (' ./ ... / models / todo ')

Du måste ha några doser som ska användas under test. Men dessa till-dos kommer att raderas från testdatabasen varje gång du kör din testpaket. För att hantera det, skapa två tester som så.

# server / test / server.test.js const todos = [_id: nytt ObjectId (), text: "First test todo", _id: nytt ObjectId (), text: "Second test todo" , completedAt: 333] beforeEach ((done) => Todo.remove , sedan (() => returnera Todo.insertMany (todos)) )

Det tidigare blocket rensar din Todo-databas och lägger sedan in doseringssatsen ovan. Detta säkerställer att du har en stabil mängd poster i din databas så att dina test inte löser problem.

Med det gjort kan du skriva testet för POSTA begäran. För din POSTA begäran, kommer du att skriva två tester. Den första kommer att göra en förfrågan om ett giltigt att göra och vara framgångsrik. Den andra kommer att göra en förfrågan med en ogiltig kropp, och detta ska inte skapa ett nytt att göra.

Här är vad testet ska se ut.

# server / test / server.test.js beskriver ('POST / todos', () => // 1 det ('ska skapa en ny todo', (done) => let text = 'Test todo text' // 2 förfrågan (app) // 3 .post ('/ todos') .send (text) .expect (200) .expect ((res) => expect (res.body.text) .toBe text)) .end ((err, res) => // 4 om (err) return done (err) Todo.find (text). då ((todos) => // 5 förvänta (todos.length) .toBe (1) expect (todos [0] .text) .toBe (text) done ()) catch ((e) => gjort (e))) skapa inte med ogiltiga kroppsdata ", (gjort) => // 6 begäran (app) // 7 .post ('/ todos') .send () .expect (400) .end ( res) => om (err) return done (err) Todo.find (). då ((todos) => // 8 förvänta (todos.length) .toBe (2) done ()). fånga (e) => gjort (e)))))

Kör testet med kommandot:

npm-körtest

Det borde misslyckas. Här är vad som händer:

  1. Beskriver testet.
  2. Skapar ett nytt att göra och sparar det som ett värde för text.
  3. Du gör en POST-förfrågan till / todos sökvägen till ditt API, skicka den du skapade som begäran. Du förväntar dig att statuskoden för begäran ska vara 200 och kroppens uppgift att motsvara värdet av text.
  4. Ett fel returneras om det finns några, och det kommer att göra att begäran slutar. Således kommer inte nästa kvarter att köra. Om inget fel uppstår fortsätter flödet.
  5. En begäran görs till databasen för att hitta den skapade att göra. Du förväntar dig att längden på dosen i databasen ska vara 1, och texten på den som ska vara lika med värdet av texten.
  6. Detta är testet som gjordes med ogiltiga kroppsdata.
  7. en POSTA begäran lämnas till / todos väg. Den här gången skickar du en förfrågan utan kropp. Du förväntar dig att få en 400 begäran. Du behöver inte kolla kroppen eftersom du inte skickar någon. Om ett fel uppstår, kommer det tillbaka och koden slutar köra.
  8. Om inget fel uppstått görs en begäran till databasen för att kontrollera längden på dosen. Vi förväntar oss att databasen kommer att innehålla endast 2, vilket är den till-dos som skapades i början.

För att få detta test passerar, gå till din server.js fil och släpp i koden som behövs för POST-förfrågan.

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

GET-förfrågan test

Detta är enkelt - testet bör returnera längden på dosen som finns tillgänglig i databasen. Som du redan vet bör längden på todos vara 2. Varför? Du gissade rätt. I början av testpaketet skapade du en beforeEach blockera det som rensar din databas och lägger in ny till-dos varje gång testpaketet körs.

För att testa att begäran om att få allt till-dos fungerar, här är koden för det.

# server / test / server.test.js beskriver ('GET / todos', () => it ('ska få alla todos', (done) => request (app) .get ('/ todos') .expect (200) .expect ((res) => (förvänta (res.body.todos.length) .toBe (2)) .end (gjort)))

I ovanstående gör du en SKAFFA SIG begäran till / todos väg. Den här gången passerar du inte något som begäran, eftersom det är a SKAFFA SIG begäran. Du förväntar dig att få ett svar med statuskoden för 200. Då räknar du med att längden på dosen kommer att vara 2.

När du kör testet ska du få ett fel. Försök få felet att skicka på egen hand.

Jag slår vad om att du fick det att fungera. Här är koden för att få testet att passera; jämför det med din lösning.

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

När en SKAFFA SIG begäran lämnas till / todos sökväg, du vill hitta alla saker i Todo-samlingen och returnera dem som till-dos. Lägger till detta till server.js får testet att passera.

Därefter ska du skriva tre tester för SKAFFA SIG begäran om att hämta individuell dosering. Den första ska hämta och returnera uppgiften. Den andra och tredje ska återvända 404 fel i fall där handlingen inte hittas.

Öppna din server.test.js och skapa ett nytt beskrivningsblock med det första testfallet.

# server / server.test.js beskriver ('GET / todos /: id', () => det ('ska returnera 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 (gjort))

Detta test gör en SKAFFA SIG begära att hämta den första åtgärd som finns tillgänglig i din databas. Du förväntar dig att få en 200 statuskod, och kontrollera att textvärdet för uppgiften är detsamma som det som skapades.

Nästa test ser ut så här.

 ('returnerar 404 om todo inte hittas', (gjort) => let _id = nytt ObjectId ('5967989ee978311656e93a59') begäran (app) .get ('/ todos / $ todos / _id.toHexString () ') .expect (404) .end (done))

Här letar du efter en uppgift med ett ID som inte motsvarar ID-en för alla som sparas i din databas. Testet förväntar sig att denna begäran ska returnera en 404 fel.

Det sista testet är som det första men lite annorlunda; här är hur det ser ut.

 det ('ska returnera 404 för icke-objekt-ID', (gjort) => let hexId = '5967989ee978311656e93a5312' begäran (app) .get ('/ todos / $ todos / hexId') .expect (404). slutet (gjort)))

Här skapar du ett ogiltigt ObjectId och försök att fråga databasen för att få en att göra som matchar ObjectId skapats. Testet förväntar sig att begäran om att returnera a 404 fel. 

När du kör testet ska de alla misslyckas. För att få dem att passera, lägg till koden nedan till din server.js fil.

# server / server.js app.get ('/ todos /: id', (req, res) => låt id = req.params.id // 1 om (! ObjectId.isValid (id)) // 2 returnera res.status (404) .send ('ID är inte giltigt') Todo.findById (id) .then ((todo) => if (! Todo) // 3 return res.status (404) .send () res.send (todo // //). fångst ((e) => res.status (400) .send ()))
  1. Hämta ID-numret på de begärda uppgifterna från parametrarna.
  2. Kontrollera om ID-numret är giltigt. Om ID-kortet inte är giltigt skickas ett fel som anger detta.
  3. Om ID-en är giltig, försök att hitta ett uppdrag som matchar det ID med hjälp av findById metod. Om det inte finns något att göra med det ID, a 404 fel skickas.
  4. Om ett handhavande hittas, skickas handlingen. Då tar du något fel som uppstår och skickar det.

Kör testkommandot en gång till, och det ska gå över.

DELETE Request Test

Testet för din RADERA Förfrågan kommer att vara lite som vad du har för din GET-förfrågan.

Först vill du testa att en att göra är raderad.

# server / test / server.test.js beskriver ('DELETE / todos /: id', () => it ('ska ta bort en todo', (done) => låt hexId = todos [0] ._ id .toHexString () // 1 begäran (app) .delete ('/ todos / $ hexId') .expect (200) .expect ((res) => förvänta (res.body.todo._id) .toBe (hexId)) .end ((err, res) => // 2 om (err) return done (err)) Todo.findById (hexId) .then ((todo) => // 3 förvänta (todo.hexId) .toNotExist () gjort ()). fånga ((e) => gjort (e)))

Här är vad som händer ovan:

  1. Du ställer in id-iden till en variabel som heter hexId. Därefter a RADERA Förfrågan görs till sökandens sökväg, med hjälp av ID. Du förväntar dig att få en 200 svaret och den uppgift som erhållits för att matcha värdet av hexId.
  2. Om något fel uppstår, returneras det.
  3. Om inget fel går testet vidare för att fråga din databas med det ID som sparats som värdet av hexId. Sedan a RADERA Förfrågan har tidigare skickats, testet förväntar sig att det att göra som matchar det ID inte existerar.

Därefter vill du testa att när en begäran görs för att radera ett uppdrag som inte existerar innehåller svaret a 404 fel. Det är viktigt att ha detta, eftersom det inte är möjligt att ta bort en handling två gånger. Så här ska testet för detta se ut.

# server / test / server.test.js det ('ska returnera 404 om todo inte hittas', (done) => let hexId = ny ObjectId (). toHexString () begäran (app) .delete ('/ todos / $ todos / hexId ') .expect (404) .end (gjort))

Detta skapar ett ID för en uppgift som inte finns i databasen. Då en RADERA Förfrågan görs för att ta bort uppgiften. Testet förväntas returnera a 404 ett fel eftersom handlingen inte existerar.

Du vill testa det a RADERA använder ett ogiltigt ID returnerar a 404 fel, som så.

# server / test / server.test.js det ('ska returnera 404 för icke-objekt ids', (gjort) => request (app) .delete ('/ todos / 123abc') .expect (404). (Gjort) ) )

För att få testet att passera, öppna din server.js och släpp det här.

# server / server.js app.delete ('/ todos /: id', (req, res) => låt id = req.params.id om (! 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 ()))

Kör kommandot för att testa:

npm-körtest

Och dina tester ska passera.

Slutsats

Nu vet du hur du konfigurerar en testpaket när du bygger ett API med Node.js. Du har använt Mocha, Expect och Supertest för att testa ett API. En fördel med att göra det här är att du inte behöver ställa upp Postman när du bygger ditt API. Med ditt test kan du lära känna vad som är trasigt.

Innan vi sätter ihop, notera att JavaScript har blivit ett av de faktiska språken för att arbeta på webben. Det är inte utan sina inlärningskurvor, och det finns gott om ramar och bibliotek för att hålla dig upptagen också. Om du letar efter ytterligare resurser att studera eller använda i ditt arbete, kolla vad vi har tillgängligt på Envato Market.

Med hjälp av vad du nu vet är du bra att utforska testningsvärlden.