Deutsch

Ein umfassender Leitfaden für Integrationstests mit Fokus auf API-Tests mit Supertest, der Setup, Best Practices und fortgeschrittene Techniken für robuste Anwendungstests behandelt.

Integrationstests: API-Tests mit Supertest meistern

Im Bereich der Softwareentwicklung ist es entscheidend sicherzustellen, dass einzelne Komponenten isoliert korrekt funktionieren (Unit-Tests). Es ist jedoch ebenso wichtig zu überprüfen, ob diese Komponenten nahtlos zusammenarbeiten. Hier kommen Integrationstests ins Spiel. Integrationstests konzentrieren sich auf die Validierung der Interaktion zwischen verschiedenen Modulen oder Diensten innerhalb einer Anwendung. Dieser Artikel befasst sich eingehend mit Integrationstests, insbesondere mit API-Tests mit Supertest, einer leistungsstarken und benutzerfreundlichen Bibliothek zum Testen von HTTP-Assertions in Node.js.

Was sind Integrationstests?

Integrationstests sind eine Art von Softwaretests, bei denen einzelne Softwaremodule kombiniert und als Gruppe getestet werden. Ihr Ziel ist es, Fehler in den Interaktionen zwischen integrierten Einheiten aufzudecken. Im Gegensatz zu Unit-Tests, die sich auf einzelne Komponenten konzentrieren, überprüfen Integrationstests den Daten- und Kontrollfluss zwischen den Modulen. Gängige Ansätze für Integrationstests umfassen:

Im Kontext von APIs beinhaltet das Integrationstesting die Überprüfung, ob verschiedene APIs korrekt zusammenarbeiten, ob die zwischen ihnen übergebenen Daten konsistent sind und ob das Gesamtsystem wie erwartet funktioniert. Stellen Sie sich zum Beispiel eine E-Commerce-Anwendung mit separaten APIs für Produktmanagement, Benutzerauthentifizierung und Zahlungsabwicklung vor. Integrationstests würden sicherstellen, dass diese APIs korrekt kommunizieren, sodass Benutzer Produkte durchsuchen, sich sicher anmelden und Einkäufe abschließen können.

Warum sind API-Integrationstests wichtig?

API-Integrationstests sind aus mehreren Gründen von entscheidender Bedeutung:

Stellen Sie sich eine globale Reisebuchungsplattform vor. API-Integrationstests sind von größter Bedeutung, um eine reibungslose Kommunikation zwischen APIs für Flugreservierungen, Hotelbuchungen und Zahlungsgateways aus verschiedenen Ländern zu gewährleisten. Eine fehlerhafte Integration dieser APIs könnte zu falschen Buchungen, Zahlungsausfällen und einer schlechten Benutzererfahrung führen, was sich negativ auf den Ruf und den Umsatz der Plattform auswirken würde.

Einführung in Supertest: Ein leistungsstarkes Werkzeug für API-Tests

Supertest ist eine High-Level-Abstraktion zum Testen von HTTP-Anfragen. Es bietet eine komfortable und flüssige API zum Senden von Anfragen an Ihre Anwendung und zum Überprüfen der Antworten. Supertest baut auf Node.js auf und ist speziell für das Testen von Node.js-HTTP-Servern konzipiert. Es funktioniert außergewöhnlich gut mit beliebten Test-Frameworks wie Jest und Mocha.

Schlüsselfunktionen von Supertest:

Einrichten Ihrer Testumgebung

Bevor wir beginnen, richten wir eine grundlegende Testumgebung ein. Wir gehen davon aus, dass Sie Node.js und npm (oder yarn) installiert haben. Wir werden Jest als unser Test-Framework und Supertest für API-Tests verwenden.

  1. Erstellen Sie ein Node.js-Projekt:
mkdir api-testing-example
cd api-testing-example
npm init -y
  1. Installieren Sie die Abhängigkeiten:
npm install --save-dev jest supertest
npm install express  # Or your preferred framework for creating the API
  1. Konfigurieren Sie Jest: Fügen Sie Folgendes zu Ihrer package.json-Datei hinzu:
{
  "scripts": {
    "test": "jest"
  }
}
  1. Erstellen Sie einen einfachen API-Endpunkt: Erstellen Sie eine Datei namens app.js (oder ähnlich) mit dem folgenden Code:
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; // Für Tests exportieren

Schreiben Ihres ersten Supertest-Tests

Nachdem wir unsere Umgebung eingerichtet haben, schreiben wir einen einfachen Supertest-Test, um unseren API-Endpunkt zu überprüfen. Erstellen Sie eine Datei namens app.test.js (oder ähnlich) im Stammverzeichnis Ihres Projekts:

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!');
  });
});

Erklärung:

Um den Test auszuführen, führen Sie den folgenden Befehl in Ihrem Terminal aus:

npm test

Wenn alles korrekt eingerichtet ist, sollten Sie sehen, dass der Test erfolgreich ist.

Fortgeschrittene Supertest-Techniken

Supertest bietet eine breite Palette von Funktionen für fortgeschrittene API-Tests. Lassen Sie uns einige davon erkunden.

1. Senden von Request-Bodies

Um Daten im Request-Body zu senden, können Sie die Methode .send() verwenden. Erstellen wir zum Beispiel einen Endpunkt, der JSON-Daten akzeptiert:

app.post('/users', express.json(), (req, res) => {
  const { name, email } = req.body;
  // Simuliert das Erstellen eines Benutzers in einer Datenbank
  const user = { id: Date.now(), name, email };
  res.status(201).json(user);
});

So können Sie diesen Endpunkt mit Supertest testen:

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);
  });
});

Erklärung:

2. Setzen von Headern

Um benutzerdefinierte Header in Ihren Anfragen zu setzen, können Sie die Methode .set() verwenden. Dies ist nützlich zum Setzen von Authentifizierungstoken, Inhaltstypen oder anderen benutzerdefinierten Headern.

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 () => {
    // Simuliert das Abrufen eines gültigen Tokens
    const token = 'valid-token';

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

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

Erklärung:

3. Umgang mit Cookies

Supertest kann auch mit Cookies umgehen. Sie können Cookies mit der Methode .set('Cookie', ...) setzen oder die Eigenschaft .cookies verwenden, um auf Cookies zuzugreifen und diese zu ändern.

4. Testen von Datei-Uploads

Supertest kann verwendet werden, um API-Endpunkte zu testen, die Datei-Uploads verarbeiten. Sie können die Methode .attach() verwenden, um Dateien an die Anfrage anzuhängen.

5. Verwendung von Assertions-Bibliotheken (Chai)

Obwohl die eingebaute Assertions-Bibliothek von Jest für viele Fälle ausreicht, können Sie auch leistungsfähigere Assertions-Bibliotheken wie Chai mit Supertest verwenden. Chai bietet eine ausdrucksstärkere und flexiblere Assertions-Syntax. Um Chai zu verwenden, müssen Sie es installieren:

npm install --save-dev chai

Dann können Sie Chai in Ihre Testdatei importieren und seine Assertions verwenden:

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!');
  });
});

Hinweis: Möglicherweise müssen Sie Jest so konfigurieren, dass es korrekt mit Chai funktioniert. Dies beinhaltet oft das Hinzufügen einer Setup-Datei, die Chai importiert und es für die Zusammenarbeit mit dem globalen expect von Jest konfiguriert.

6. Wiederverwenden von Agents

Für Tests, die die Einrichtung einer speziellen Umgebung erfordern (z. B. Authentifizierung), ist es oft vorteilhaft, einen Supertest-Agenten wiederzuverwenden. Dies vermeidet redundanten Setup-Code in jedem Testfall.

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

  beforeAll(() => {
    agent = request.agent(app); // Einen persistenten Agenten erstellen
    // Authentifizierung simulieren
    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 () => {
    // Führen Sie hier andere authentifizierte Aktionen aus
  });
});

In diesem Beispiel erstellen wir einen Supertest-Agenten im beforeAll-Hook und authentifizieren den Agenten. Nachfolgende Tests innerhalb des describe-Blocks können diesen authentifizierten Agenten dann wiederverwenden, ohne sich für jeden Test erneut authentifizieren zu müssen.

Best Practices für API-Integrationstests mit Supertest

Um effektive API-Integrationstests zu gewährleisten, beachten Sie die folgenden Best Practices:

Häufige Fehler, die es zu vermeiden gilt

Fazit

API-Integrationstests sind ein wesentlicher Bestandteil des Softwareentwicklungsprozesses. Mit Supertest können Sie einfach umfassende und zuverlässige API-Integrationstests schreiben, die dazu beitragen, die Qualität und Stabilität Ihrer Anwendung sicherzustellen. Denken Sie daran, sich auf das Testen von End-to-End-Workflows zu konzentrieren, realistische Daten zu verwenden, Ihre Tests zu isolieren und Ihren Testprozess zu automatisieren. Durch die Befolgung dieser Best Practices können Sie das Risiko von Integrationsproblemen erheblich reduzieren und ein robusteres und zuverlässigeres Produkt liefern.

Da APIs weiterhin moderne Anwendungen und Microservices-Architekturen antreiben, wird die Bedeutung robuster API-Tests, insbesondere von Integrationstests, nur noch zunehmen. Supertest bietet Entwicklern weltweit ein leistungsstarkes und zugängliches Werkzeugset, um die Zuverlässigkeit und Qualität ihrer API-Interaktionen zu gewährleisten.