Testowanie, choć może być czasochłonne, jest ważnym krokiem w cyklu rozwoju każdej aplikacji. Gwarantuje, że wyłapujesz błędy i problemy na wczesnym etapie, zanim wypchniesz kod do środowiska produkcyjnego.

Możesz użyć Jest do testowania interfejsu Express Rest API. Po utworzeniu prostego interfejsu API CRUD odkryj, jak pisać testy dla każdego punktu końcowego.

Czym jest błahostka?

Istnieje wiele bibliotek testujących JavaScript, z których możesz wybierać, ale Żart jest najłatwiejszy na początek. Jest to biblioteka testowa opracowana przez Facebooka, używana głównie do testowania projektów React. Możesz go jednak również użyć do testowania Node i innych projektów opartych na JavaScript. Został opracowany na bazie Jasmine, innego narzędzia testowego, i jest dostarczany z własną biblioteką asercji.

Chociaż nie będziesz potrzebować biblioteki asercji do pisania testów w Jest, będziesz potrzebować narzędzia do tworzenia żądań HTTP. Ten artykuł wykorzystuje SuperTest.

Co to jest supertest?

Supertest

instagram viewer
to biblioteka testowania węzłów dla wywołań HTTP. Rozszerza bibliotekę testowania superagentów i umożliwia wykonywanie żądań, takich jak GET, POST, PUT i DELETE.

SuperTest udostępnia obiekt żądania, którego możesz użyć do tworzenia żądań HTTP.

stały żądanie = wymagać(„supertest”)
żądanie("https://icanhazdadjoke.com")
.Dostawać('/slack')
.koniec(funkcjonować(błądzić, res) {
jeśli (błądzić) rzucić błądzić;
konsola.dziennik(res.ciało.załączniki);
});

Tutaj przekazujesz podstawowy adres URL interfejsu API do obiektu żądania, a następnie łączysz metodę HTTP z resztą adresu URL. The koniec() Metoda wywołuje serwer API, a funkcja wywołania zwrotnego obsługuje jego odpowiedź.

Po otrzymaniu odpowiedzi z interfejsu API możesz użyć Jest, aby ją zweryfikować.

Utwórz ekspresowe API

Aby przetestować własne punkty końcowe API, musisz utworzyć REST API pierwszy. Interfejs API, który utworzysz, jest dość prosty. Wstawia, pobiera, aktualizuje i usuwa elementy z tablicy.

Zacznij od utworzenia nowego katalogu o nazwie node-jest i zainicjowania npm.

mkdir node-jest
npm początek -y

Następnie utwórz nowy plik o nazwie index.js oraz utwórz serwer Express.

stały ekspres = wymagać("wyrazić")
stały aplikacja = ekspres ()
app.słuchaj (3000, () => konsola.log("Nasłuch na porcie 3000"))

Przetestuj punkt końcowy GET /todos

Pierwszym punktem końcowym, który utworzysz, jest punkt końcowy GET /todos. Zwraca wszystkie elementy tablicy. W index.js dodaj następujące.

stały rzeczy do zrobienia = [
];
// Pobierz wszystkie rzeczy do zrobienia
aplikacja.pobierz("/todos", (wymagane, odp.) => {
zwrócićres.status(200).json({
dane: rzeczy do zrobienia,
błąd: zero,
});
});

Zauważ, że odpowiedź ma kod stanu 200 i obiekt JSON zawierający element do zrobienia w tablicy o nazwie data i komunikat o błędzie. To właśnie przetestujesz za pomocą Jest.

Teraz zainstaluj Jest i SuperTest:

npm zainstalować po prostu supertest

Następnie dodaj skrypt testowy w pakiet.json następująco:

{
"skrypty": {
"test": "żart"
}
}

Zanim zaczniesz pisać własne testy, powinieneś zrozumieć, jak napisać podstawowy test w Jest.

Rozważ następującą funkcję:

funkcjonowaćsuma(a, b) {
zwrócić a + b;
}
moduł.eksport = suma;

W pliku testowym musisz:

  • Zaimportuj funkcję.
  • Opisz, co powinien zrobić test.
  • Wywołaj funkcję.
  • Połącz oczekiwaną odpowiedź z rzeczywistą odpowiedzią funkcji.
stały { suma } = wymagać("./suma")
opisać("Suma dwóch przedmiotów", asynchroniczna() => {
test("Powinien zwrócić 4", () => {
oczekiwać(suma(2,2)).być(4)
})
})

The opisać słowo kluczowe określa grupę testów, a test oświadczenie określa konkretny test. Jeśli wartość zwrócona z funkcji jest zgodna z wartością przekazaną do byćtest przechodzi.

Testując punkty końcowe API, nie będziesz wywoływać funkcji, ale wysyłasz żądanie za pomocą SuperTestu lub innej biblioteki klienta HTTP.

Wracając do punktu końcowego GET, utwórz nowy plik o nazwie api.test.js. Tutaj napiszesz wszystkie testy punktów końcowych. Nazywanie pliku testowego za pomocą .test infix zapewnia, że ​​Jest rozpoznaje go jako plik testowy.

W api.test.js zaimportuj supertest i ustaw podstawowy adres URL w następujący sposób:

stały żądanie = wymagać(„supertest”)
stały bazowy URL = "http://host lokalny: 3000"

Następnie utwórz pierwszy test w bloku opisu:

opisać("POBIERZ /todos", () => {
stały nowe zadanie = {
ID: krypto.randomUUID(),
przedmiot: "Pij wodę",
zakończony: fałszywy,
}
przed wszystkim(asynchroniczny () => {
// ustaw zadanie
czekaj na żądanie (baseURL).post("/todo").wyślij (noweTodo);
})
w końcu(asynchroniczny () => {
czekać na request (baseURL).delete(`/do zrobienia/${noweTodo.id}`)
})
to("powinien wrócić 200", asynchroniczny () => {
stały odpowiedź = czekać na request (baseURL).get("/todos");
oczekiwać(odpowiedź.Kod statusu).być(200);
oczekiwać(odpowiedź.ciało.błąd).być(zero);
});
to("powinien wrócić do rzeczy", asynchroniczny () => {
stały odpowiedź = czekać na request (baseURL).get("/todos");
oczekiwać (response.body.data.length >= 1).być(PRAWDA);
});
});

Przed uruchomieniem testów należy zdefiniować funkcje konfiguracji i usuwania. Te funkcje zapełnią tablicę zadań do wykonania elementem przed testem i usuną dane fikcyjne po każdym teście.

Kod uruchamiany przed wszystkimi testami znajduje się w funkcji beforeAll(). Kod uruchamiany po wszystkich testach znajduje się w funkcji afterAll().

W tym przykładzie po prostu trafiasz do punktów końcowych POST i DELETE dla każdego z nich. W prawdziwej aplikacji prawdopodobnie połączysz się z próbną bazą danych zawierającą dane testowe.

W tym teście najpierw wysłałeś żądanie do punktu końcowego GET /todos i porównałeś odpowiedź wysłaną z powrotem z oczekiwanymi wynikami. Ten zestaw testów przejdzie, jeśli odpowiedź ma Kod stanu HTTP 200, dane nie są puste, a komunikat o błędzie ma wartość NULL.

Przetestuj POST /todo Endpoint

W index.js utwórz punkt końcowy POST /todo:

aplikacja.post("/todo", (wymagane, odp.) => {
próbować {
stały { id, pozycja, ukończona } = zam.body;
stały nowe zadanie = {
ID,
przedmiot,
zakończony,
};
rzeczy do zrobienia.naciskać(nowośćTodo);
zwrócićres.status(201).json({
dane: rzeczy do zrobienia,
błąd: zero,
});
} złapać (błąd) {
zwrócićres.status(500).json({
dane: zero,
błąd: błąd,
});
}
});

W tym teście będziesz musiał wysłać szczegóły todo w treści żądania za pomocą metody send().

żądanie (baseURL).post("/todo").send (noweTodo)

Żądanie POST /todo powinno zwrócić kod statusu 201 i tablicę rzeczy do zrobienia z dodaną nową pozycją na końcu. Oto jak może wyglądać test:

opisać("POST /todo", () => {
stały nowe zadanie = {
// do zrobienia
}
w końcu(asynchroniczny () => {
czekać na request (baseURL).delete(`/do zrobienia/${noweTodo.id}`)
})
to("powinien dodać element do tablicy todos", asynchroniczny () => {
stały odpowiedź = czekać na request (baseURL).post("/todo").send(newTodo);
stały lastItem = response.body.data[response.body.data.length-1]
oczekiwać(odpowiedź.Kod statusu).być(201);
oczekiwać(Ostatnia sztuka.przedmiot).być(nowośćTodo["przedmiot"]);
oczekiwać(Ostatnia sztuka.zakończony).być(nowośćTodo["zakończony"]);
});
});

Tutaj przekazujesz dane rzeczy do zrobienia do metody send() jako argument. Odpowiedź powinna mieć kod stanu 201, a także zawierać wszystkie elementy do zrobienia w obiekcie danych. Aby sprawdzić, czy zadanie zostało rzeczywiście utworzone, sprawdź, czy ostatni wpis w zwróconych zadaniach odpowiada temu, który wysłałeś w żądaniu.

Punkt końcowy PUT /todos/:id powinien zwrócić zaktualizowany element:

aplikacja.put("/todos/:id", (wymagane, odp.) => {
próbować {
stały id = wymagane.parametry.id
stały todo = todos.find((todo) => todo.id == id);
jeśli(!todo) {
rzucićNowyBłąd(„Nie znaleziono rzeczy do zrobienia”)
}
todo.completed = żądane.body.completed;
zwrócićres.status(201).json({
dane: do zrobienia,
błąd: zero,
});
} złapać (błąd) {
zwrócićres.status(500).json({
dane: zero,
błąd: błąd,
});
}
});

Przetestuj odpowiedź w następujący sposób:

opisać("Zaktualizuj jedno zadanie", () => {
stały nowe zadanie = {
// do zrobienia
}
przed wszystkim(asynchroniczny () => {
czekaj na żądanie (baseURL).post("/todo").wyślij (noweTodo);
})
w końcu(asynchroniczny () => {
czekać na request (baseURL).delete(`/do zrobienia/${noweTodo.id}`)
})
to("powinien zaktualizować element, jeśli istnieje", asynchroniczny () => {
stały odpowiedź = czekać na żądanie (baseURL).put(`/todos/${noweTodo.id}`).wysłać({
zakończony: PRAWDA,
});
oczekiwać(odpowiedź.Kod statusu).być(201);
oczekiwać(odpowiedź.ciało.dane.zakończony).być(PRAWDA);
});
});

Uzupełniona wartość w treści odpowiedzi powinna być prawdziwa. Pamiętaj, aby w adresie URL podać identyfikator elementu, który chcesz zaktualizować.

Przetestuj DELETE /todos/:id Endpoint

W index.js utwórz punkt końcowy DELETE. Powinien zwrócić dane do zrobienia bez usuniętego elementu.

aplikacja.usuń("/todos/:id", (wymagane, odp.) => {
próbować {
stały id = wymagane.parametry.id
stały rzeczy do zrobienia = rzeczy do zrobienia[0]
jeśli (do zrobienia) {
rzeczy do zrobienia.splatać(ID, 1)
}
zwrócićres.status(200).json({
dane: rzeczy do zrobienia,
błąd: zero,
});
} złapać (błąd) {
zwrócićres.status(500).json({
dane: zero,
błąd: błąd,
});
}
});

Aby przetestować punkt końcowy, możesz sprawdzić, czy usunięty element nadal istnieje w zwróconych danych:

opisać("Usuń jedno zadanie", () => {
stały nowe zadanie = {
// do zrobienia
}
przed wszystkim(asynchroniczny () => {
czekaj na żądanie (baseURL).post("/todo").wyślij (noweTodo);
})
to("powinien usunąć jeden element", asynchroniczny () => {
stały odpowiedź = czekać na request (baseURL).delete(`/todos/${noweTodo.id}`);
stały todos = odpowiedź.body.data
stały istnieje = todos.znajdź (todo => {
newTodo.id == todoId
})
oczekiwać (istnieje).toBe(nieokreślony)
});
});

Dane zwrócone z punktu końcowego DELETE nie powinny zawierać usuniętego elementu. Ponieważ zwrócone elementy znajdują się w tablicy, możesz użyć Array[id], aby sprawdzić, czy API poprawnie usunął element. Wynik powinien być fałszywy.

Tworzenie interfejsów API REST

Z tego artykułu dowiesz się, jak testować interfejs API Express Rest za pomocą interfejsu API Jest. Napisałeś testy dla żądań HTTP GET, PUT, POST i DELETE i zobaczyłeś, jak wysyłać dane do punktu końcowego w adresie URL i żądaniu. Powinieneś być w stanie zastosować tę wiedzę podczas testowania własnego interfejsu API Rest.