Testing, selv om det kan være tidkrevende, er et viktig skritt i utviklingssyklusen til enhver applikasjon. Det sikrer at du oppdager feil og problemer tidlig før du sender kode til produksjon.
Du kan bruke Jest til å teste en Express Rest API. Etter at du har laget et enkelt CRUD API, kan du finne ut hvordan du skriver tester for hvert endepunkt.
Hva er Jest?
Det er mange JavaScript-testbiblioteker du kan velge mellom, men Spøk er den enkleste å begynne med. Det er et testbibliotek utviklet av Facebook, mest brukt til å teste React-prosjekter. Du kan imidlertid også bruke den til å teste Node og andre JavaScript-baserte prosjekter. Den ble utviklet på toppen av Jasmine, et annet testverktøy, og kommer sammen med sitt eget påstandsbibliotek.
Selv om du ikke trenger et påstandsbibliotek for å skrive tester i Jest, må du bruke et verktøy for å lage HTTP-forespørsler. Denne artikkelen bruker SuperTest.
Hva er SuperTest?
SuperTest er et nodetestbibliotek for HTTP-anrop. Den utvider superagent testbiblioteket og lar deg gjøre forespørsler som GET, POST, PUT og DELETE.
SuperTest gir et forespørselsobjekt du kan bruke til å lage HTTP-forespørsler.
konst forespørsel = krever("supertest")
be om("https://icanhazdadjoke.com")
.få('/slack')
.slutt(funksjon(feil, res) {
hvis (feil) kaste feile;
konsoll.Logg(res.kropp.vedlegg);
});
Her sender du basis-URLen til API-et til forespørselsobjektet og kobler deretter HTTP-metoden sammen med resten av URL-en. De slutt() metode kaller API-serveren og tilbakeringingsfunksjonen håndterer svaret.
Når du får svaret fra API, kan du bruke Jest til å validere det.
Opprett en Express API
For å teste dine egne API-endepunkter, må du opprette et REST API først. APIen du skal lage er ganske enkel. Den setter inn, henter, oppdaterer og sletter elementer fra en matrise.
Begynn med å lage en ny katalog kalt node-jest og initialisere npm.
mkdir node-jest
npm init -y
Deretter oppretter du en ny fil kalt index.js og opprette Express-serveren.
konst uttrykke = krever("uttrykke")
konst app = express()
app.listen (3000, () => console.log("Lytter på port 3000"))
Test GET /todos-endepunktet
Det første endepunktet du vil opprette er GET /todos-endepunktet. Den returnerer alle elementene i matrisen. I index.js legger du til følgende.
konst gjøremål = [
];
// Få alle gjøremål
app.get("/todos", (req, res) => {
komme tilbakeres.status(200).json({
data: gjøremål,
feil: null,
});
});
Merk at svaret har en statuskode på 200 og et JSON-objekt som inneholder gjøremålselementet i en matrise kalt data og en feilmelding. Dette er hva du vil teste med Jest.
Installer nå Jest og SuperTest:
npm installere spøkefull supertest
Deretter legger du til et testskript package.json følgende:
{
"skript": {
"test": "spøk"
}
}
Før du begynner å skrive dine egne tester, bør du forstå hvordan du skriver en grunnleggende test i Jest.
Tenk på følgende funksjon:
funksjonsum(a, b) {
komme tilbake a + b;
}
modul.eksport = sum;
I testfilen må du:
- Importer funksjonen.
- Beskriv hva testen skal gjøre.
- Ring funksjonen.
- Bekreft den forventede responsen med den faktiske responsen fra funksjonen.
konst { sum } = krever("./sum")
beskrive("Summen av to elementer", asynkron() => {
test("Den skal returnere 4", () => {
forvente(sum(2,2)).å være(4)
})
})
De beskrive nøkkelordet spesifiserer gruppen av tester og test uttalelse spesifiserer den spesifikke testen. Hvis verdien returnert fra funksjonen samsvarer med verdien sendt til å være, testen består.
Når du tester API-endepunkter, vil du ikke kalle en funksjon, men sende en forespørsel ved hjelp av SuperTest eller et annet HTTP-klientbibliotek.
Gå tilbake til GET-endepunktet, opprett en ny fil kalt api.test.js. Det er her du skal skrive alle endepunktstestene. Navngi testfilen med en .test infix sikrer at Jest gjenkjenner den som en testfil.
I api.test.js importerer du supertest og setter basis-URLen slik:
konst forespørsel = krever("supertest")
konst baseURL = "http://localhost: 3000"
Deretter oppretter du den første testen i beskriv-blokken:
beskrive("FÅ /todos", () => {
konst newTodo = {
id: krypto.randomUUID(),
punkt: "Drikk vann",
fullført: falsk,
}
førAlle(asynkron () => {
// sette opp gjøremålet
vent request (baseURL).post("/todo").send (newTodo);
})
tross alt(asynkron () => {
avvente request (baseURL).delete(`/todo/${newTodo.id}`)
})
den("skal returnere 200", asynkron () => {
konst svar = avvente request (baseURL).get("/todos");
forvente(respons.statuskode).å være(200);
forvente(respons.kropp.feil).å være(null);
});
den("bør returnere todos", asynkron () => {
konst svar = avvente request (baseURL).get("/todos");
forventer (response.body.data.length >= 1).å være(ekte);
});
});
Før du kjører testene, må du definere oppsetts- og nedbyggingsfunksjoner. Disse funksjonene vil fylle todo-matrisen med et element før testen og slette dummy-dataene etter hver test.
Koden som kjøres før alle testene er i beforeAll()-funksjonen. Koden som kjøres etter alle testene er i afterAll()-funksjonen.
I dette eksemplet treffer du ganske enkelt POST- og DELETE-endepunktene for hver. I en ekte applikasjon vil du sannsynligvis koble deg til en falsk database som inneholder testdataene.
I denne testen sendte du først en forespørsel til GET /todos-endepunktet og sammenlignet svaret som ble sendt tilbake med de forventede resultatene. Denne testpakken vil bestå hvis svaret har en HTTP-statuskode av 200, er dataene ikke tomme, og feilmeldingen er null.
Test POST /todo-endepunktet
I index.js oppretter du POST /todo-endepunktet:
app.post("/todo", (req, res) => {
prøve {
konst { id, item, completed } = req.body;
konst newTodo = {
id,
punkt,
fullført,
};
todos.trykk(newTodo);
komme tilbakeres.status(201).json({
data: gjøremål,
feil: null,
});
} å fange (feil) {
komme tilbakeres.status(500).json({
data: null,
feil: feil,
});
}
});
I denne testen må du sende gjøremålsdetaljene i forespørselsteksten ved å bruke send()-metoden.
request (baseURL).post("/todo").send (newTodo)
POST /todo-forespørselen skal returnere en 201-statuskode og todos-matrisen med det nye elementet lagt til på slutten. Slik kan testen se ut:
beskrive("POST /todo", () => {
konst newTodo = {
// å gjøre
}
tross alt(asynkron () => {
avvente request (baseURL).delete(`/todo/${newTodo.id}`)
})
den("bør legge til et element i todos-arrayen", asynkron () => {
konst svar = avvente request (baseURL).post("/todo").send(newTodo);
konst lastItem = response.body.data[response.body.data.length-1]
forvente(respons.statuskode).å være(201);
forvente(siste vare.punkt).å være(newTodo["punkt"]);
forvente(siste vare.fullført).å være(newTodo["fullført"]);
});
});
Her sender du todo-dataene til send()-metoden som et argument. Svaret skal ha en 201-statuskode og også inneholde alle gjøremålene i et dataobjekt. For å teste om todo faktisk ble opprettet, sjekk om den siste oppføringen i de returnerte todosene samsvarer med den du sendte i forespørselen.
PUT /todos/:id-endepunktet skal returnere det oppdaterte elementet:
app.put("/todos/:id", (req, res) => {
prøve {
konst id = req.params.id
konst todo = todos.find((todo) => todo.id == id);
if(!todo) {
kastenyFeil("Todo ikke funnet")
}
todo.completed = req.body.completed;
komme tilbakeres.status(201).json({
data: gjøremål,
feil: null,
});
} å fange (feil) {
komme tilbakeres.status(500).json({
data: null,
feil: feil,
});
}
});
Test svaret som følger:
beskrive("Oppdater én gjøremål", () => {
konst newTodo = {
// å gjøre
}
førAlle(asynkron () => {
vent request (baseURL).post("/todo").send (newTodo);
})
tross alt(asynkron () => {
avvente request (baseURL).delete(`/todo/${newTodo.id}`)
})
den("bør oppdatere elementet hvis det eksisterer", asynkron () => {
konst svar = avvente request (baseURL).put(`/todos/${newTodo.id}`).sende({
fullført: ekte,
});
forvente(respons.statuskode).å være(201);
forvente(respons.kropp.data.fullført).å være(ekte);
});
});
Den fullførte verdien i svarteksten skal være sann. Husk å inkludere ID-en til elementet du vil oppdatere i URL-en.
Test DELETE /todos/:id-endepunktet
I index.js oppretter du DELETE-endepunktet. Den skal returnere gjøremålsdataene uten det slettede elementet.
app.delete("/todos/:id", (req, res) => {
prøve {
konst id = req.params.id
konst gjøremål = gjøremål[0]
if (todo) {
todos.spleise(id, 1)
}
komme tilbakeres.status(200).json({
data: gjøremål,
feil: null,
});
} å fange (feil) {
komme tilbakeres.status(500).json({
data: null,
feil: feil,
});
}
});
For å teste endepunktet kan du sjekke om det slettede elementet fortsatt eksisterer i de returnerte dataene:
beskrive("Slett én gjøremål", () => {
konst newTodo = {
// å gjøre
}
førAlle(asynkron () => {
vent request (baseURL).post("/todo").send (newTodo);
})
den("bør slette ett element", asynkron () => {
konst svar = avvente request (baseURL).delete(`/todos/${newTodo.id}`);
konst todos = respons.kroppsdata
konst eksisterer = todos.finn (todo => {
newTodo.id == todoId
})
forventer (eksisterer).toBe(udefinert)
});
});
Dataene som returneres fra DELETE-endepunktet skal ikke inneholde det slettede elementet. Siden de returnerte varene er i en matrise, kan du bruke Array[id] for å sjekke om APIen slettet varen på riktig måte. Resultatet skal være falskt.
Opprette REST APIer
I denne artikkelen lærte du hvordan du tester en Express Rest API ved hjelp av Jest API. Du skrev tester for GET, PUT, POST og SLETT HTTP-forespørslene og så hvordan du kunne sende data til endepunktet i URL-en og forespørselen. Du bør kunne bruke denne kunnskapen når du tester din egen Rest API.