Polski

Kompleksowy przewodnik po testach integracyjnych, skupiający się na testowaniu API za pomocą Supertest, obejmujący konfigurację, najlepsze praktyki i zaawansowane techniki.

Testy integracyjne: Opanowanie testowania API za pomocą Supertest

W świecie tworzenia oprogramowania, kluczowe jest zapewnienie, że poszczególne komponenty działają poprawnie w izolacji (testy jednostkowe). Równie ważne jest jednak sprawdzenie, czy te komponenty płynnie ze sobą współpracują. W tym miejscu do gry wchodzą testy integracyjne. Testy integracyjne koncentrują się na weryfikacji interakcji między różnymi modułami lub usługami w aplikacji. Ten artykuł zagłębia się w testy integracyjne, ze szczególnym uwzględnieniem testowania API za pomocą Supertest, potężnej i przyjaznej dla użytkownika biblioteki do testowania asercji HTTP w Node.js.

Czym są testy integracyjne?

Testy integracyjne to rodzaj testowania oprogramowania, który łączy poszczególne moduły oprogramowania i testuje je jako grupę. Celem jest wykrycie defektów w interakcjach między zintegrowanymi jednostkami. W przeciwieństwie do testów jednostkowych, które koncentrują się na poszczególnych komponentach, testy integracyjne weryfikują przepływ danych i przepływ sterowania między modułami. Typowe podejścia do testów integracyjnych obejmują:

W kontekście API, testy integracyjne polegają na weryfikacji, czy różne API działają poprawnie razem, czy dane przekazywane między nimi są spójne i czy cały system funkcjonuje zgodnie z oczekiwaniami. Wyobraźmy sobie na przykład aplikację e-commerce z oddzielnymi API do zarządzania produktami, uwierzytelniania użytkowników i przetwarzania płatności. Testy integracyjne zapewniłyby, że te API komunikują się poprawnie, umożliwiając użytkownikom przeglądanie produktów, bezpieczne logowanie i dokonywanie zakupów.

Dlaczego testowanie integracyjne API jest ważne?

Testowanie integracyjne API jest kluczowe z kilku powodów:

Rozważmy globalną platformę rezerwacji podróży. Testowanie integracyjne API jest kluczowe dla zapewnienia płynnej komunikacji między API obsługującymi rezerwacje lotów, rezerwacje hoteli i bramki płatnicze z różnych krajów. Nieprawidłowa integracja tych API mogłaby prowadzić do błędnych rezerwacji, nieudanych płatności i złego doświadczenia użytkownika, negatywnie wpływając na reputację i przychody platformy.

Przedstawiamy Supertest: Potężne narzędzie do testowania API

Supertest to wysokopoziomowa abstrakcja do testowania żądań HTTP. Zapewnia wygodne i płynne API do wysyłania żądań do aplikacji i sprawdzania odpowiedzi. Zbudowany na Node.js, Supertest jest specjalnie zaprojektowany do testowania serwerów HTTP w Node.js. Działa wyjątkowo dobrze z popularnymi frameworkami testowymi, takimi jak Jest i Mocha.

Kluczowe cechy Supertest:

Konfiguracja środowiska testowego

Zanim zaczniemy, skonfigurujmy podstawowe środowisko testowe. Zakładamy, że masz zainstalowany Node.js i npm (lub yarn). Użyjemy Jest jako naszego frameworka testowego i Supertest do testowania API.

  1. Stwórz projekt Node.js:
mkdir api-testing-example
cd api-testing-example
npm init -y
  1. Zainstaluj zależności:
npm install --save-dev jest supertest
npm install express  # Lub preferowany framework do tworzenia API
  1. Skonfiguruj Jest: Dodaj następujący fragment do pliku package.json:
{
  "scripts": {
    "test": "jest"
  }
}
  1. Stwórz prosty punkt końcowy API: Utwórz plik o nazwie app.js (lub podobnej) z następującym kodem:
const express = require('express');
const app = express();
const port = 3000;

app.get('/hello', (req, res) => {
  res.send('Hello, World!');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

module.exports = app; // Eksportuj do celów testowych

Pisanie pierwszego testu z Supertest

Teraz, gdy mamy już skonfigurowane środowisko, napiszmy prosty test z Supertest, aby zweryfikować nasz punkt końcowy API. Utwórz plik o nazwie app.test.js (lub podobnej) w głównym katalogu projektu:

const request = require('supertest');
const app = require('./app');

describe('GET /hello', () => {
  it('responds with 200 OK and returns "Hello, World!"', async () => {
    const response = await request(app).get('/hello');
    expect(response.statusCode).toBe(200);
    expect(response.text).toBe('Hello, World!');
  });
});

Wyjaśnienie:

Aby uruchomić test, wykonaj następujące polecenie w terminalu:

npm test

Jeśli wszystko jest poprawnie skonfigurowane, powinieneś zobaczyć, że test przechodzi pomyślnie.

Zaawansowane techniki Supertest

Supertest oferuje szeroki zakres funkcji do zaawansowanego testowania API. Przyjrzyjmy się niektórym z nich.

1. Wysyłanie ciała żądania

Aby wysłać dane w ciele żądania, możesz użyć metody .send(). Na przykład, stwórzmy punkt końcowy, który akceptuje dane w formacie JSON:

app.post('/users', express.json(), (req, res) => {
  const { name, email } = req.body;
  // Symulacja tworzenia użytkownika w bazie danych
  const user = { id: Date.now(), name, email };
  res.status(201).json(user);
});

Oto jak można przetestować ten punkt końcowy za pomocą Supertest:

describe('POST /users', () => {
  it('creates a new user', async () => {
    const userData = {
      name: 'John Doe',
      email: 'john.doe@example.com',
    };

    const response = await request(app)
      .post('/users')
      .send(userData)
      .expect(201);

    expect(response.body).toHaveProperty('id');
    expect(response.body.name).toBe(userData.name);
    expect(response.body.email).toBe(userData.email);
  });
});

Wyjaśnienie:

2. Ustawianie nagłówków

Aby ustawić niestandardowe nagłówki w żądaniach, możesz użyć metody .set(). Jest to przydatne do ustawiania tokenów uwierzytelniających, typów zawartości lub innych niestandardowych nagłówków.

describe('GET /protected', () => {
  it('requires authentication', async () => {
    const response = await request(app).get('/protected').expect(401);
  });

  it('returns 200 OK with a valid token', async () => {
    // Symulacja uzyskania ważnego tokenu
    const token = 'valid-token';

    const response = await request(app)
      .get('/protected')
      .set('Authorization', `Bearer ${token}`)
      .expect(200);

    expect(response.text).toBe('Protected Resource');
  });
});

Wyjaśnienie:

3. Obsługa plików cookie

Supertest potrafi również obsługiwać pliki cookie. Możesz ustawić pliki cookie za pomocą metody .set('Cookie', ...) lub użyć właściwości .cookies, aby uzyskać dostęp i modyfikować pliki cookie.

4. Testowanie przesyłania plików

Supertest może być używany do testowania punktów końcowych API, które obsługują przesyłanie plików. Możesz użyć metody .attach(), aby dołączyć pliki do żądania.

5. Używanie bibliotek asercji (Chai)

Chociaż wbudowana biblioteka asercji Jesta jest wystarczająca w wielu przypadkach, z Supertest można również używać potężniejszych bibliotek asercji, takich jak Chai. Chai zapewnia bardziej wyrazistą i elastyczną składnię asercji. Aby użyć Chai, należy go zainstalować:

npm install --save-dev chai

Następnie możesz zaimportować Chai do swojego pliku testowego i używać jego asercji:

const request = require('supertest');
const app = require('./app');
const chai = require('chai');
const expect = chai.expect;

describe('GET /hello', () => {
  it('responds with 200 OK and returns "Hello, World!"', async () => {
    const response = await request(app).get('/hello');
    expect(response.statusCode).to.equal(200);
    expect(response.text).to.equal('Hello, World!');
  });
});

Uwaga: Może być konieczne skonfigurowanie Jesta do poprawnej współpracy z Chai. Często wiąże się to z dodaniem pliku konfiguracyjnego, który importuje Chai i konfiguruje go do pracy z globalnym expect Jesta.

6. Ponowne wykorzystywanie agentów

W przypadku testów wymagających skonfigurowania określonego środowiska (np. uwierzytelniania) często korzystne jest ponowne wykorzystanie agenta Supertest. Pozwala to uniknąć zbędnego kodu konfiguracyjnego w każdym przypadku testowym.

describe('Authenticated API Tests', () => {
  let agent;

  beforeAll(() => {
    agent = request.agent(app); // Utwórz trwałego agenta
    // Symulacja uwierzytelniania
    return agent
      .post('/login')
      .send({ username: 'testuser', password: 'password123' });
  });

  it('can access a protected resource', async () => {
    const response = await agent.get('/protected').expect(200);
    expect(response.text).toBe('Protected Resource');
  });

  it('can perform other actions that require authentication', async () => {
    // Wykonaj inne uwierzytelnione akcje tutaj
  });
});

W tym przykładzie tworzymy agenta Supertest w haku beforeAll i go uwierzytelniamy. Kolejne testy w bloku describe mogą następnie ponownie wykorzystać tego uwierzytelnionego agenta, bez konieczności ponownego uwierzytelniania dla każdego testu.

Najlepsze praktyki w testowaniu integracyjnym API z Supertest

Aby zapewnić skuteczne testowanie integracyjne API, rozważ następujące najlepsze praktyki:

Częste błędy, których należy unikać

Podsumowanie

Testowanie integracyjne API jest istotną częścią procesu tworzenia oprogramowania. Używając Supertest, możesz łatwo pisać kompleksowe i niezawodne testy integracyjne API, które pomagają zapewnić jakość i stabilność Twojej aplikacji. Pamiętaj, aby skupić się na testowaniu kompleksowych przepływów pracy, używaniu realistycznych danych, izolowaniu testów i automatyzacji procesu testowania. Postępując zgodnie z tymi najlepszymi praktykami, możesz znacznie zmniejszyć ryzyko problemów integracyjnych i dostarczyć bardziej solidny i niezawodny produkt.

Ponieważ API nadal napędzają nowoczesne aplikacje i architektury mikroserwisów, znaczenie solidnego testowania API, a zwłaszcza testów integracyjnych, będzie tylko rosło. Supertest dostarcza potężny i dostępny zestaw narzędzi dla programistów na całym świecie, aby zapewnić niezawodność i jakość interakcji ich API.