example-petstore.com

Beispieldomain · Kein aktiver Dienst · Browseraufrufe zeigen diese Seite · API-Anfragen erhalten 410 Gone

Anleitung · Tests

Gegen eine Mock-API testen, nicht gegen einen Platzhalter

Code, der auf eine erfundene Adresse wie api.example-petstore.com zeigt, sendet trotzdem echte Anfragen, und diese erreichen den, dem der Name gehört. Eine Mock-API bietet denselben Komfort ohne dieses Risiko: Sie läuft auf Ihrem eigenen Rechner oder in Ihren Tests, antwortet sofort und liefert immer die Daten, die Sie erwarten.

Warum kein Platzhalter

  • Ein Platzhalter, der wie eine echte Domain aussieht, kann von jemand anderem registriert sein. Jede Anfrage, einschließlich Headern mit Schlüsseln oder Tokens, landet dann auf dessen Server.
  • Unbenutzte Namen unter example.com, etwa api.example.com, lösen gar nicht auf, sodass der Code mit einem Timeout oder DNS-Fehler scheitert, statt zu zeigen, wie er mit echten Antworten umgeht.
  • Tests, die von einem öffentlichen Server abhängen, sind langsam und unzuverlässig, und sie brechen, sobald sich dieser Server ändert.

Eine Mock-API löst alle drei Probleme: Sie lauscht auf localhost oder im Testprozess, und nichts verlässt Ihren Rechner.

Welches Tool wann

ToolAm besten fürLäuft als
PrismSie haben eine OpenAPI-Beschreibung und möchten Antworten, die ihr folgenLokaler Server (Node.js oder Docker), Port 4010
WireMockExakte, aufgezeichnete Antworten, Fehlerfälle und Verzögerungen für jede SpracheLokaler Server (Java oder Docker), Port 8080
MSWJavaScript und TypeScript: Frontend-Entwicklung und Unit-TestsIm Browser oder im Node.js-Testprozess
json-serverEine funktionierende REST-API aus einer JSON-Datei, für PrototypenLokaler Server (Node.js), Port 3000

Für die Beispiel-API Swagger Petstore selbst betreiben Sie das offizielle Image lokal; siehe Sie suchen den Swagger Petstore?

Prism: aus einer OpenAPI-Datei

Prism liest eine OpenAPI-Beschreibung (oder Swagger 2.0) und beantwortet jede darin enthaltene Operation mit den Beispielen oder Schemas aus dieser Datei. Anfragen, die nicht zur Beschreibung passen, erhalten einen klaren Validierungsfehler. Damit lässt sich ein Client prüfen, bevor die echte API existiert.

# Mit Node.js
npm install -g @stoplight/prism-cli
prism mock openapi.yaml

# Mit Docker
docker run --init --rm -v "$(pwd)":/tmp -p 4010:4010 stoplight/prism:5 mock -h 0.0.0.0 /tmp/openapi.yaml

# Danach
curl http://127.0.0.1:4010/pets
curl http://127.0.0.1:4010/pets/1 -H "Prefer: code=404"

Der Header Prefer wählt eine bestimmte Antwort aus der Beschreibung, etwa einen Fehlercode oder ein benanntes Beispiel. Mit --dynamic (-d) erzeugt Prism bei jeder Anfrage neue Daten aus den Schemas.

WireMock: aufgezeichnete Antworten

WireMock antwortet aus Stub-Dateien, die Sie schreiben oder aufzeichnen. Es eignet sich für jede Programmiersprache und kann langsame Antworten und Ausfälle simulieren, die ein echter Dienst selten auf Abruf liefert.

# mocks/mappings/pet.json
{
  "request":  { "method": "GET", "url": "/v1/pets/1" },
  "response": {
    "status": 200,
    "headers": { "Content-Type": "application/json" },
    "jsonBody": { "id": 1, "name": "Rex", "status": "available" }
  }
}

# Mit dem Ordner starten, der mappings/ enthält (und __files/ für größere Bodies)
docker run -it --rm -p 8080:8080 -v "$(pwd)/mocks":/home/wiremock wiremock/wiremock

curl http://localhost:8080/v1/pets/1

Fügen Sie einer Antwort "fixedDelayMilliseconds": 3000 hinzu, um Timeouts zu testen, oder einen Status wie 503, um Wiederholungsversuche zu testen. Über die Admin-API unter /__admin können Tests Stubs hinzufügen und prüfen, welche Anfragen eingegangen sind.

MSW und PHP-Mocks: in Ihren Tests

Mock Service Worker fängt Anfragen innerhalb der Anwendung selbst ab: im Browser über einen Service Worker, in Node.js innerhalb des Testprozesses. Der getestete Code ruft weiterhin seine normale Basis-URL auf; es läuft kein zusätzlicher Server.

// handlers.js
import { http, HttpResponse } from 'msw'

export const handlers = [
  http.get('https://api.example.com/v1/pets/:id', ({ params }) =>
    HttpResponse.json({ id: Number(params.id), name: 'Rex', status: 'available' })),
  http.post('https://api.example.com/v1/pets', () =>
    HttpResponse.json({ error: 'name is required' }, { status: 400 })),
]

// In Tests (Node.js)
import { setupServer } from 'msw/node'
const server = setupServer(...handlers)
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

onUnhandledRequest: 'error' lässt einen Test fehlschlagen, sobald Code eine Adresse ohne Handler aufruft. So fällt ein vergessener Platzhalter im Testlauf auf statt in der Produktion. Führen Sie im Browser einmalig npx msw init public/ aus und starten Sie den Worker aus msw/browser.

In PHP-Tests erledigt der MockHandler von Guzzle dasselbe innerhalb des Testprozesses, und Symfony bietet MockHttpClient:

// PHP, Guzzle: antwortet der Reihe nach, ohne Netzwerk
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;

$mock = new MockHandler([
    new Response(200, ['Content-Type' => 'application/json'], '{"id": 1, "name": "Rex", "status": "available"}'),
    new Response(400, [], '{"error": "name is required"}'),
]);
$client = new Client(['handler' => HandlerStack::create($mock), 'base_uri' => 'https://api.example.com/v1/']);

// PHP, Symfony
$client = new Symfony\Component\HttpClient\MockHttpClient(
    [new Symfony\Component\HttpClient\Response\MockResponse('{"id": 1, "name": "Rex"}')],
    'https://api.example.com/v1/'
);

Die Adresse in den Handlern ist api.example.com: ein reservierter Name, der nie einen echten Server erreicht, selbst wenn eine Anfrage am Mock vorbeirutscht.

json-server: eine schnelle REST-API

json-server macht aus einer JSON-Datei eine REST-API mit Routen zum Auflisten, Abrufen, Anlegen, Ändern und Löschen. Änderungen werden in die Datei zurückgeschrieben, was für Prototypen und Demos praktisch ist.

# db.json
{
  "pets":   [ { "id": "1", "name": "Rex", "status": "available" } ],
  "orders": []
}

npx json-server db.json

curl http://localhost:3000/pets
curl -X POST http://localhost:3000/orders -H "Content-Type: application/json" -d '{"petId": "1"}'

json-server bietet weder Validierung noch Authentifizierung und eignet sich daher nur für Prototypen; für Contract-Tests sind Prism oder WireMock besser geeignet.

Wechsel zur echten API

Legen Sie die Basis-URL in der Konfiguration ab, mit dem Mock als Wert für Entwicklung und Tests und der echten Adresse nur dort, wo die Anwendung tatsächlich läuft:

# .env.development
API_BASE_URL=http://localhost:4010

# .env.test
API_BASE_URL=http://localhost:8080

# Produktion: in der Hosting-Umgebung setzen, nie im Repository
API_BASE_URL=https://api.your-real-service.com

Mehr dazu, einschließlich einer Prüfung, die Beispieladressen von der Produktion fernhält: API-Clients und SDKs konfigurieren.

Quellen