DEV Community

Cover image for API Mocking für Tests: Eine praktische Anleitung
Emre Demir
Emre Demir

Posted on • Originally published at apidog.com

API Mocking für Tests: Eine praktische Anleitung

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.

Testen Sie Apidog noch heute

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:

  1. Schema definieren: Beschreiben Sie die erwartete Antwortform.
  2. Mock-Antworten generieren: Statisch oder dynamisch aus dem Schema.
  3. Mock-Server starten: Lokal oder gehostet.
  4. Tests auf den Mock ausrichten: Basis-URL konfigurierbar machen.
  5. Fehlerpfade testen: 404, 429, 500, Timeouts und ungültige Bodies prüfen.

Im Beispiel verwenden wir diesen Endpunkt:

GET /orders/{id}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

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": []
}
Enter fullscreen mode Exit fullscreen mode

Besseres Beispiel:

{
  "id": "order_8842",
  "status": "shipped",
  "total": 149.99,
  "items": [
    {
      "sku": "sku_keyboard",
      "quantity": 1
    },
    {
      "sku": "sku_mouse",
      "quantity": 2
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Danach ist der Beispiel-Endpunkt lokal erreichbar:

curl http://127.0.0.1:4010/orders/order_8842
Enter fullscreen mode Exit fullscreen mode

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();
}
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

In CI setzen Sie dann nur die Umgebungsvariable:

API_BASE_URL=http://127.0.0.1:4010 npm test
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

Apidogs erweiterte Mock-Regeln können unterschiedliche Antworten basierend auf der Anfrage zurückgeben. Zum Beispiel:

  • GET /orders/order_8842200
  • GET /orders/order_404404
  • GET /orders/order_rate_limited429
  • 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Nicht so:

test-1.json
test-checkout-flow.json
my-mock.json
Enter fullscreen mode Exit fullscreen mode

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
};
Enter fullscreen mode Exit fullscreen mode

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. total zu amount
  • 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 Requests mit Retry-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)