Tests, die von einer Live-API abhängen, schlagen oft aus den falschen Gründen fehl: Staging ist offline, ein Drittanbieter limitiert Requests, Testdaten ändern sich. API-Mocking ersetzt den echten Endpunkt durch einen kontrollierten Platzhalter, der reproduzierbar genau die Antwort liefert, die Ihr Test braucht.
In diesem Leitfaden setzen Sie einen API-Mock für Tests praktisch um: Schema definieren, Mock-Antworten erzeugen, Mock-Server starten, Tests auf den Mock zeigen lassen und Fehlerfälle gezielt prüfen. Als Beispiel dient eine kleine Auftragsverwaltungs-API mit GET /orders/{id}. Der Ablauf funktioniert genauso für REST- und GraphQL-APIs.
Wann API-Mocking sinnvoll ist
Mocken Sie die API, wenn Sie Ihren eigenen Code testen wollen, nicht das Netzwerk.
Typische Fälle:
- Unit-Tests für API-Clients
- Integrationstests gegen abhängige Services
- Tests für Retry-, Timeout- und Fehlerlogik
- Frontend-Entwicklung, bevor das Backend fertig ist
Behalten Sie echte API-Aufrufe für Vertragstests und wenige End-to-End-Tests. Diese prüfen, ob Ihr Mock noch zur Produktion passt. Die Faustregel:
- Mocks für Geschwindigkeit, Isolation und deterministische Tests
- Live-API für Vertragsprüfung und produktionsnahe End-to-End-Flows
Mehr Kontext finden Sie in den Szenarien, in denen sich API-Mocking auszahlt, und im Vergleich zwischen Mock-Server und realem Server.
Der Workflow in 5 Schritten
API-Mocking für Tests folgt immer demselben Muster:
- Schema definieren: Beschreiben Sie die erwartete Antwortform.
- Mock-Antworten generieren: Statisch oder dynamisch aus dem Schema.
- Mock-Server starten: Lokal oder gehostet.
- Tests auf den Mock ausrichten: Basis-URL konfigurierbar machen.
-
Fehlerpfade testen:
404,429,500, Timeouts und ungültige Bodies prüfen.
Im Beispiel verwenden wir diesen Endpunkt:
GET /orders/{id}
Schritt 1: Schema definieren
Ein Mock ist nur nützlich, wenn er den tatsächlichen API-Vertrag abbildet. Nutzen Sie ein vorhandenes OpenAPI-Dokument oder definieren Sie den relevanten Endpunkt selbst.
Beispiel für GET /orders/{id}:
paths:
/orders/{id}:
get:
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: Order found
content:
application/json:
schema:
type: object
required:
- id
- status
- total
- items
properties:
id:
type: string
status:
type: string
enum: [pending, shipped, delivered]
total:
type: number
items:
type: array
items:
type: object
'404':
description: Order not found
Dieses Schema ist Ihre Quelle der Wahrheit. Es beschreibt:
- welche Felder existieren
- welche Typen erwartet werden
- welche Statuscodes unterstützt werden
- welche Werte für Enums erlaubt sind
Schema-basiertes Mocking hält auch API-Vertragstests konsistent: Wenn sich der Vertrag ändert, aktualisieren Sie das Schema und generieren daraus die Mocks neu.
Schritt 2: Mock-Antworten generieren
Sie können Mock-Daten auf zwei Arten erzeugen.
Option A: Statische Antworten
Eine statische Antwort ist festes JSON. Sie eignet sich für Tests mit konkreten Assertions.
{
"id": "order_8842",
"status": "shipped",
"total": 149.99,
"items": [
{
"sku": "sku_keyboard",
"quantity": 1
},
{
"sku": "sku_mouse",
"quantity": 1
}
]
}
Vorteile:
- deterministisch
- einfach zu debuggen
- ideal für Unit-Tests
- stabil für Snapshot- oder Assertion-lastige Tests
Option B: Dynamische Antworten
Dynamische Antworten werden pro Request generiert. Statt 149.99 fest zu codieren, erzeugt der Mock realistische Werte wie:
- UUIDs für
id - gültige Enum-Werte für
status - plausible Zahlen für
total - unterschiedliche Array-Längen für
items
Das deckt Parser- und Validierungsfehler auf, die eine einzelne statische Payload verstecken kann.
Mit Apidog können Sie Mock-Endpunkte direkt aus dem Schema erzeugen. Apidog liest Feldnamen wie email, phone oder avatar und generiert passende Datentypen. Sie rufen die Mock-URL auf und erhalten sofort eine gültige Antwort.
Wenn Sie Payloads manuell schreiben, halten Sie sie produktionsnah:
- keine unrealistischen leeren Objekte als Standard
- gültige Enum-Werte verwenden
- mehrere Listenelemente testen
- Grenzwerte gezielt als eigene Szenarien ablegen
Schlechtes Beispiel:
{
"id": "1",
"status": "x",
"total": 0,
"items": []
}
Besseres Beispiel:
{
"id": "order_8842",
"status": "shipped",
"total": 149.99,
"items": [
{
"sku": "sku_keyboard",
"quantity": 1
},
{
"sku": "sku_mouse",
"quantity": 2
}
]
}
Schritt 3: Mock-Server starten
Eine Mock-Antwort muss unter einer URL erreichbar sein. Dafür gibt es zwei typische Varianten.
Lokaler Mock-Server
Ein lokaler Mock-Server läuft auf Ihrem Rechner, zum Beispiel unter localhost:4010. Er ist ideal für Unit- und Integrationstests:
- schnell
- offline verfügbar
- kein gemeinsamer Zustand zwischen Builds
- gut für CI geeignet
Mit Prism können Sie einen Mock direkt aus einer OpenAPI-Datei starten:
prism mock openapi.yaml
# Mock server listening on http://127.0.0.1:4010
Danach ist der Beispiel-Endpunkt lokal erreichbar:
curl http://127.0.0.1:4010/orders/order_8842
Cloud-Mock-Server
Ein Cloud-Mock-Server hat eine öffentliche URL. Nutzen Sie ihn, wenn andere Umgebungen denselben Mock erreichen müssen:
- mobile Apps
- externe Entwickler
- CI-Runner ohne lokalen Mock-Start
- Demos
- Tests auf mehreren Geräten
Apidog stellt für Projekte gehostete Cloud-Mock-URLs bereit, sodass Teammitglieder denselben Mock-Endpunkt verwenden können.
Für automatisierte Testläufe ist lokal meist die bessere Wahl. Für Demos und Cross-Device-Tests ist ein Cloud-Mock praktischer.
Schritt 4: Tests auf den Mock ausrichten
Der wichtigste Implementierungsdetail: Hardcoden Sie keine Produktions-URL im Client. Machen Sie die Basis-URL konfigurierbar.
Beispiel mit JavaScript:
// orderClient.js
export async function getOrder(id, baseUrl) {
const response = await fetch(`${baseUrl}/orders/${id}`);
if (response.status === 404) {
throw new Error(`Order ${id} not found`);
}
if (!response.ok) {
throw new Error(`API request failed with ${response.status}`);
}
return response.json();
}
Test gegen den Mock:
// orderClient.test.js
import { getOrder } from './orderClient.js';
const BASE_URL = process.env.API_BASE_URL || 'http://127.0.0.1:4010';
test('parst eine versendete Bestellung', async () => {
const order = await getOrder('order_8842', BASE_URL);
expect(order.status).toBe('shipped');
expect(typeof order.total).toBe('number');
expect(Array.isArray(order.items)).toBe(true);
});
In CI setzen Sie dann nur die Umgebungsvariable:
API_BASE_URL=http://127.0.0.1:4010 npm test
Dieses Muster hält Mocking aus der Produktionslogik heraus. Der Client kennt nur eine Basis-URL; ob dahinter Produktion, Staging oder ein Mock liegt, entscheidet die Umgebung.
Dasselbe Prinzip gilt, wenn Sie API-Tests in CI/CD automatisieren.
Schritt 5: Fehlerpfade testen
Hier bringt Mocking besonders viel Nutzen. Ein echter Server liefert selten genau dann einen 500, wenn Sie Ihre Fehlerbehandlung testen wollen. Ein Mock kann das jederzeit.
Prüfen Sie mindestens diese Szenarien:
| Szenario | Mock gibt zurück | Erwartetes Verhalten |
|---|---|---|
| Fehlender Datensatz | 404 |
Client wirft einen klaren „nicht gefunden“-Fehler |
| Serverfehler | 500 |
Client versucht es erneut oder zeigt einen Fallback |
| Ratenlimit |
429 mit Retry-After
|
Client wartet oder reduziert Requests |
| Langsame Antwort |
200 nach 5 Sekunden |
Client bricht per Timeout ab |
| Fehlerhafter Body |
200 mit ungültigem JSON |
Client schlägt kontrolliert fehl |
Beispieltest für 404:
test('wirft einen klaren Fehler bei fehlender Bestellung', async () => {
await expect(
getOrder('order_404', BASE_URL)
).rejects.toThrow('Order order_404 not found');
});
Beispieltest für ungültige Antwortform:
test('validiert die Antwortform', async () => {
const order = await getOrder('order_invalid_shape', BASE_URL);
expect(order).toHaveProperty('id');
expect(order).toHaveProperty('status');
expect(order).toHaveProperty('total');
expect(order).toHaveProperty('items');
});
Apidogs erweiterte Mock-Regeln können unterschiedliche Antworten basierend auf der Anfrage zurückgeben. Zum Beispiel:
-
GET /orders/order_8842→200 -
GET /orders/order_404→404 -
GET /orders/order_rate_limited→429 -
GET /orders/order_timeout→ verzögerte Antwort
Kombinieren Sie solche Szenarien mit starken API-Assertions, damit Ihre Tests Verhalten prüfen, nicht nur Statuscodes.
Mocks in einer wachsenden Test-Suite organisieren
Ein Mock-Endpunkt ist einfach. Viele Mock-Endpunkte werden schnell unübersichtlich. Nutzen Sie klare Strukturen.
Nach realem Service gruppieren
Gruppieren Sie Mocks nach dem Dienst, den sie ersetzen:
mocks/
orders/
order-shipped.json
order-not-found.json
order-rate-limited.json
payments/
payment-success.json
payment-declined.json
So müssen Sie bei einer Änderung der Orders-API nicht mehrere Testdateien durchsuchen.
Szenarien statt Tests benennen
Benennen Sie Fixtures nach dem Verhalten, das sie repräsentieren:
order-shipped.json
order-pending.json
order-not-found.json
order-invalid-body.json
Nicht so:
test-1.json
test-checkout-flow.json
my-mock.json
Ein fehlgeschlagener Test sollte sofort erkennen lassen, welches API-Szenario betroffen ist.
Basisantwort wiederverwenden
Viele Tests brauchen dieselbe realistische Antwort mit nur einer Änderung. Definieren Sie eine Basisantwort und überschreiben Sie einzelne Felder.
Beispiel:
const baseOrder = {
id: 'order_8842',
status: 'shipped',
total: 149.99,
items: [
{ sku: 'sku_keyboard', quantity: 1 }
]
};
const pendingOrder = {
...baseOrder,
status: 'pending'
};
const expensiveOrder = {
...baseOrder,
total: 9999.99
};
Das reduziert Duplikate und macht Vertragsänderungen einfacher. Dieselbe Disziplin, die eine Test-Suite für API-Automatisierung wartbar macht, gilt auch für Mocks.
Den Mock aktuell halten
Mocks können vom echten Backend abweichen. Typische Ursachen:
- Feld wurde umbenannt, z. B.
totalzuamount - neues Pflichtfeld wurde hinzugefügt
- Enum-Werte wurden geändert
- Fehlerformat wurde angepasst
- Statuscode hat sich geändert
Dann bleiben Mock-basierte Tests grün, obwohl Produktion bricht.
Verhindern Sie das mit zwei Regeln.
1. Mock aus demselben Schema generieren
Nutzen Sie dasselbe OpenAPI-Schema für:
- API-Dokumentation
- Mock-Server
- Vertragstests
- Client-Tests
Wenn das Backend den Vertrag ändert, wird der Mock aus dem aktualisierten Schema neu erzeugt.
2. Regelmäßig gegen die echte API testen
Führen Sie eine kleine Menge Vertragstests gegen die Live- oder Staging-API aus. Diese Tests prüfen nicht jeden UI-Flow, sondern nur:
- passt die Antwort noch zum Schema?
- sind Pflichtfelder vorhanden?
- stimmen Typen und Enums?
- entsprechen Fehlerantworten dem Vertrag?
Wenn diese Tests fehlschlagen, ist Ihr Mock wahrscheinlich veraltet.
3. Mocks im Code Review prüfen
Wenn ein Pull Request eine API-Antwort ändert, sollte auch der passende Mock angepasst werden. Behandeln Sie Mocks nicht als Wegwerf-Fixtures, sondern als Teil des API-Vertrags.
Wenn Sie eine Umgebung möchten, die Schema, Mock-Server und Tests zusammenhält, können Sie Apidog herunterladen. Für weitere Optionen lohnt sich der Vergleich von REST-API-Mocking-Tools.
Häufig gestellte Fragen
Sollte ich die API für jeden Test mocken?
Nein. Mocken Sie Unit- und Integrationstests, bei denen Sie Ihren eigenen Code prüfen. Behalten Sie eine kleine Menge Vertragstests und End-to-End-Tests gegen die echte API. Nur so erkennen Sie, ob Ihr Mock noch zur Produktion passt.
Was ist der Unterschied zwischen statischen und dynamischen Mock-Antworten?
Eine statische Mock-Antwort ist eine feste JSON-Payload. Sie ist ideal für deterministische Assertions.
Eine dynamische Mock-Antwort wird pro Request erzeugt. Sie hilft, Parser- und Validierungsfehler aufzudecken, die bei einer einzigen festen Payload verborgen bleiben.
In der Praxis verwenden viele Teams beide Varianten.
Wie stelle ich sicher, dass mein Mock korrekt bleibt?
Generieren Sie den Mock aus demselben Schema, das auch das Backend verwendet, idealerweise aus OpenAPI. Führen Sie zusätzlich regelmäßige Vertragstests gegen die echte API aus. Wenn diese fehlschlagen, muss der Mock oder das Schema aktualisiert werden.
Kann ein Mock langsame oder fehlerhafte Antworten simulieren?
Ja. Genau dafür ist Mocking besonders nützlich. Sie können gezielt simulieren:
500 Internal Server Error-
429 Too Many RequestsmitRetry-After - verzögerte
200-Antworten - ungültiges JSON
- fehlende Felder
- leere Listen
- Timeouts
Damit testen Sie Retry-Logik, Fallbacks und Fehlermeldungen zuverlässig.
Lokaler Mock-Server oder Cloud-Mock-Server für Tests?
Für automatisierte Testläufe ist ein lokaler Mock-Server meist besser: schnell, isoliert und ohne Netzwerklatenz.
Ein Cloud-Mock-Server ist sinnvoll, wenn mobile Geräte, externe Entwickler oder entfernte CI-Runner denselben Mock erreichen müssen.
Top comments (0)