Test, selvom det kan være tidskrævende, er et vigtigt skridt i udviklingscyklussen for enhver applikation. Det sikrer, at du fanger fejl og problemer tidligt, før du skubber kode til produktion.

Du kan bruge Jest til at teste en Express Rest API. Når du har oprettet en simpel CRUD API, kan du finde ud af, hvordan du skriver test for hvert slutpunkt.

Hvad er Jest?

Der er mange JavaScript-testbiblioteker, som du kan vælge imellem, men Spøg er den nemmeste at starte med. Det er et testbibliotek udviklet af Facebook, mest brugt til at teste React-projekter. Du kan dog også bruge det til at teste Node og andre JavaScript-baserede projekter. Det blev udviklet oven på Jasmine, et andet testværktøj, og leveres med sit eget påstandsbibliotek.

Selvom du ikke har brug for et påstandsbibliotek for at skrive test i Jest, skal du bruge et værktøj til at lave HTTP-anmodninger. Denne artikel bruger SuperTest.

Hvad er SuperTest?

SuperTest er et nodetestbibliotek til HTTP-opkald. Det udvider superagent-testbiblioteket og giver dig mulighed for at lave anmodninger som GET, POST, PUT og DELETE.

instagram viewer

SuperTest giver et anmodningsobjekt, du kan bruge til at lave HTTP-anmodninger.

konst anmodning = kræve("supertest")
anmodning("https://icanhazdadjoke.com")
.få('/slack')
.ende(fungere(fejl, res) {
hvis (fejl) kaste fejl;
konsol.log(res.legeme.vedhæftede filer);
});

Her sender du basis-URL'en for API'et til anmodningsobjektet og kæder derefter HTTP-metoden med resten af ​​URL'en. Det ende() metode kalder API-serveren, og tilbagekaldsfunktionen håndterer dens svar.

Når du får svaret fra API'en, kan du bruge Jest til at validere det.

Opret en Express API

For at teste dine egne API-endepunkter skal du oprette en REST API først. Den API, du vil oprette, er ret enkel. Den indsætter, henter, opdaterer og sletter elementer fra et array.

Begynd med at oprette en ny mappe kaldet node-jest og initialisere npm.

mkdir node-jost
npm init -y

Opret derefter en ny fil kaldet index.js og oprette Express-serveren.

konst udtrykke = kræve("udtrykke")
konst app = express()
app.listen (3000, () => console.log("Lytter ved port 3000"))

Test GET /todos-endepunktet

Det første slutpunkt, du vil oprette, er GET /todos-slutpunktet. Det returnerer alle elementerne i arrayet. Tilføj følgende i index.js.

konst gøremål = [
];
// Få alle gøremål
app.get("/todos", (req, res) => {
Vend tilbageres.status(200).json({
data: todos,
fejl: nul,
});
});

Bemærk, at svaret har en statuskode på 200 og et JSON-objekt, der indeholder opgave-elementet i et array kaldet data og en fejlmeddelelse. Dette er, hvad du vil teste ved hjælp af Jest.

Installer nu Jest og SuperTest:

npm installere sjov supertest

Tilføj derefter et testscript package.json som følger:

{
"scripts": {
"prøve": "spøg"
}
}

Før du begynder at skrive dine egne tests, bør du forstå, hvordan du skriver en grundlæggende test i Jest.

Overvej følgende funktion:

fungeresum(a, b) {
Vend tilbage a + b;
}
modul.eksport = sum;

I testfilen skal du:

  • Importer funktionen.
  • Beskriv, hvad testen skal gøre.
  • Kald funktionen.
  • Bekræft det forventede svar med det faktiske svar fra funktionen.
konst { sum } = kræve("./sum")
beskrive("Summen af ​​to elementer", async() => {
prøve("Den skulle vende tilbage 4", () => {
forventer(sum(2,2)).at være(4)
})
})

Det beskrive nøgleordet angiver gruppen af ​​tests og prøve statement specificerer den specifikke test. Hvis den værdi, der returneres fra funktionen, matcher den værdi, der sendes til at være, testen består.

Når du tester API-endepunkter, kalder du ikke en funktion, men sender en anmodning ved hjælp af SuperTest eller et andet HTTP-klientbibliotek.

Vend tilbage til GET-slutpunktet, opret en ny fil kaldet api.test.js. Det er her du vil skrive alle slutpunktstestene. Navngivning af testfilen med en .prøve infix sikrer, at Jest genkender den som en testfil.

Importer supertest i api.test.js og indstil basis-URL'en sådan:

konst anmodning = kræve("supertest")
konst baseURL = "http://localhost: 3000"

Opret derefter den første test i beskriv-blokken:

beskrive("FÅ /todos", () => {
konst newTodo = {
id: krypto.randomUUID(),
vare: "Drik vand",
afsluttet: falsk,
}
førAlle(asynkron () => {
// opsæt opgaven
afvent anmodning (baseURL).post("/todo").send (nyTodo);
})
trods alt(asynkron () => {
vente request (baseURL).delete(`/todo/${newTodo.id}`)
})
det("skal returnere 200", asynkron () => {
konst svar = vente request (baseURL).get("/todos");
forventer(respons.statusKode).at være(200);
forventer(respons.legeme.fejl).at være(nul);
});
det("skal returnere todos", asynkron () => {
konst svar = vente request (baseURL).get("/todos");
forventer (response.body.data.length >= 1).at være(rigtigt);
});
});

Før du kører testene, skal du definere opsætnings- og nedtagningsfunktioner. Disse funktioner vil udfylde todo-arrayet med et element før testen og slette dummy-dataene efter hver test.

Koden, der kører før alle testene, er i funktionen beforeAll(). Koden, der kører efter alle testene, er i afterAll()-funktionen.

I dette eksempel rammer du blot POST- og DELETE-slutpunkterne for hver. I en rigtig applikation ville du sandsynligvis oprette forbindelse til en falsk database, der indeholder testdataene.

I denne test lavede du først en anmodning til GET /todos-slutpunktet og sammenlignede svaret, der blev sendt tilbage, med de forventede resultater. Denne testsuite vil bestå, hvis svaret har en HTTP-statuskode af 200, er dataene ikke tomme, og fejlmeddelelsen er null.

Test POST /todo-endepunktet

I index.js skal du oprette POST /todo-slutpunktet:

app.post("/todo", (req, res) => {
prøve {
konst { id, item, completed } = req.body;
konst newTodo = {
id,
vare,
afsluttet,
};
todos.skubbe(newTodo);
Vend tilbageres.status(201).json({
data: todos,
fejl: nul,
});
} fangst (fejl) {
Vend tilbageres.status(500).json({
data: nul,
fejl: fejl,
});
}
});

I denne test skal du sende opgaveoplysningerne i anmodningsteksten ved hjælp af send()-metoden.

request (baseURL).post("/todo").send (newTodo)

POST /todo-anmodningen skal returnere en 201-statuskode og todos-arrayet med det nye element tilføjet i slutningen. Sådan kan testen se ud:

beskrive("POST /todo", () => {
konst newTodo = {
// at gøre
}
trods alt(asynkron () => {
vente request (baseURL).delete(`/todo/${newTodo.id}`)
})
det("skal tilføje et element til todos-array", asynkron () => {
konst svar = vente request (baseURL).post("/todo").send(newTodo);
konst lastItem = response.body.data[response.body.data.length-1]
forventer(respons.statusKode).at være(201);
forventer(sidste vare.vare).at være(newTodo["vare"]);
forventer(sidste vare.fuldført).at være(newTodo["fuldført"]);
});
});

Her sender du todo-dataene til send()-metoden som et argument. Svaret skal have en 201-statuskode og også indeholde alle todo-elementerne i et dataobjekt. For at teste, om todo faktisk blev oprettet, skal du kontrollere, om den sidste post i de returnerede todos svarer til den, du sendte i anmodningen.

PUT /todos/:id-slutpunktet skal returnere det opdaterede element:

app.put("/todos/:id", (req, res) => {
prøve {
konst id = req.params.id
konst todo = todos.find((todo) => todo.id == id);
if(!todo) {
kastenyFejl("Todo ikke fundet")
}
todo.completed = req.body.completed;
Vend tilbageres.status(201).json({
data: gøremål,
fejl: nul,
});
} fangst (fejl) {
Vend tilbageres.status(500).json({
data: nul,
fejl: fejl,
});
}
});

Test svaret som følger:

beskrive("Opdater en opgave", () => {
konst newTodo = {
// at gøre
}
førAlle(asynkron () => {
afvent anmodning (baseURL).post("/todo").send (nyTodo);
})
trods alt(asynkron () => {
vente request (baseURL).delete(`/todo/${newTodo.id}`)
})
det("bør opdatere elementet, hvis det findes", asynkron () => {
konst svar = vente request (baseURL).put(`/todos/${newTodo.id}`).sende({
afsluttet: rigtigt,
});
forventer(respons.statusKode).at være(201);
forventer(respons.legeme.data.fuldført).at være(rigtigt);
});
});

Den udfyldte værdi i svarteksten skal være sand. Husk at inkludere id'et for det element, du vil opdatere, i URL'en.

Test DELETE /todos/:id-slutpunktet

I index.js skal du oprette DELETE-slutpunktet. Det skulle returnere opgavedataene uden det slettede element.

app.delete("/todos/:id", (req, res) => {
prøve {
konst id = req.params.id
konst todo = gøremål[0]
if (todo) {
todos.splejsning(id, 1)
}
Vend tilbageres.status(200).json({
data: todos,
fejl: nul,
});
} fangst (fejl) {
Vend tilbageres.status(500).json({
data: nul,
fejl: fejl,
});
}
});

For at teste slutpunktet kan du kontrollere, om det slettede element stadig findes i de returnerede data:

beskrive("Slet én opgave", () => {
konst newTodo = {
// at gøre
}
førAlle(asynkron () => {
afvent anmodning (baseURL).post("/todo").send (nyTodo);
})
det("skal slette ét element", asynkron () => {
konst svar = vente request (baseURL).delete(`/todos/${newTodo.id}`);
konst todos = respons.body.data
konst eksisterer = todos.find (todo => {
newTodo.id == todoId
})
forventer (eksisterer).toBe(udefineret)
});
});

De data, der returneres fra DELETE-slutpunktet, bør ikke indeholde det slettede element. Da de returnerede varer er i et array, kan du bruge Array[id] til at kontrollere, om API'en har slettet elementet korrekt. Resultatet skal være falsk.

Oprettelse af REST API'er

I denne artikel lærte du, hvordan du tester en Express Rest API ved hjælp af Jest API. Du skrev test for GET, PUT, POST og SLET HTTP-anmodningerne og så, hvordan du sender data til slutpunktet i URL'en og anmodningen. Du bør være i stand til at anvende denne viden, når du tester din egen Rest API.