Mock API yang mengembalikan error sesuai permintaan

Dapatkan 500, 429 dengan Retry-After, timeout, atau body terpotong kapan pun tes Anda membutuhkannya.

Contoh terakhir dijalankan terhadap API pada

Untuk menguji cara kode Anda menangani API yang gagal, arahkan ke endpoint yang sengaja gagal. https://api.testingapis.com gratis, tanpa key, dan menerima request dari origin mana pun. /api/status/500 mengembalikan 500 dan /api/status/429 mengembalikan 429 dengan Retry-After. Kode apa pun dari 200 sampai 599 bisa dipakai. Menambahkan ?error=503 ke endpoint sungguhan membuatnya gagal, dan /api/chaos/retry/{key}masuk untuk melihat gagal sejumlah kali tertentu sebelum berhasil. /api/chaos/timeoutmasuk untuk melihat menggantung sampai klien Anda menyerah, dan /api/chaos/partialmasuk untuk melihat mengirim separuh response. Berikut masing-masing, beserta response yang dikembalikannya.

Endpoint mana untuk kegagalan apa

Yang ingin diujiRequestYang kembali
Kode status tertentuGET /api/status/503Status itu, body JSON, dan header yang biasanya menyertainya
Endpoint sungguhan yang gagalGET /api/Products/1?error=500Status yang Anda minta, dengan X-Simulated: true
Endpoint sungguhan yang lambatGET /api/Products/1?delay=3Response normal setelah N detik (maksimal 10)
Logika retryGET /api/chaos/retry/my-key?succeedAfter=2masuk untuk melihatDua kali gagal, lalu 200. X-Attempt menghitung percobaan
Kegagalan acakGET /api/chaos/flaky?failRate=0.3masuk untuk melihat503 dengan Retry-After: 1 sekitar 30% dari waktu
Timeout klienGET /api/chaos/timeout?seconds=30masuk untuk melihatTidak ada apa-apa sampai waktunya habis (1 sampai 60 detik)
Body terpotongGET /api/chaos/partialmasuk untuk melihatHeader menjanjikan 10.000 byte, sekitar 64 yang tiba, lalu koneksi ditutup
Rate limiting sungguhanGET /api/RateLimitmasuk untuk melihat429 setelah 5 request dalam 60 detik, dengan Retry-After
Campuran berbobotGET /api/status/random?codes=200:3,500:1200 tiga kali lebih sering daripada 500

Mengembalikan kode status HTTP apa pun

/api/status/{code} menerima metode apa pun dan merespons dengan kode di path. Ia juga mengirim header yang diharapkan klien untuk status itu: Retry-After pada 429 dan 503, WWW-Authenticate pada 401, Location pada redirect, dan Allow pada 405. Jadi Anda bisa memeriksa bahwa kode Anda membacanya, bukan hanya melihat angkanya.

Terminal
$ curl -i https://api.testingapis.com/api/status/429
HTTP/1.1 429 Too Many Requests
content-type: application/json; charset=utf-8
retry-after: 5

{"status":429,"statusText":"Too Many Requests","category":"client-error","message":"This is a 429 response. Use /api/status/{code} to request any status."}
GET/api/status/429

Membuat endpoint sungguhan gagal

Tes yang hanya memanggil /api/status/500 tidak banyak membuktikan tentang layar yang memuat produk. Tambahkan error ke request yang sudah dibuat aplikasi Anda, dan panggilan itu gagal alih-alih mengembalikan data. ?delay=N menunggu N detik lebih dulu, jadi ?delay=3&error=503 memungkinkan Anda memeriksa bahwa status memuat muncul lalu berganti menjadi pesan error.

Terminal
$ curl -i "https://api.testingapis.com/api/Products/1?error=503"
HTTP/1.1 503 Service Unavailable
x-simulated: true

{"status":503,"error":"Service Unavailable","message":"Simulated error. Use ?error={code} to test different status codes.","simulated":true}
GET/api/Products/1?error=503

Kedua parameter berlaku di semua endpoint, termasuk penulisan. Daftar lengkapnya ada di dokumentasi API.

Menguji retry tanpa menebak

Kegagalan acak membuat tes retry tidak stabil. /api/chaos/retry/{key}masuk untuk melihat bersifat deterministik: dengan succeedAfter=2, dua request pertama untuk sebuah key gagal dan yang ketiga berhasil. failStatus memilih status kegagalan (429, 500, 502, 503, atau 504), dan setiap response punya header X-Attempt, sehingga tes bisa memeriksa berapa kali klien Anda mencoba. Pakai key baru di setiap run tes, atau reset dengan DELETE.

Terminal
$ curl -i "https://api.testingapis.com/api/chaos/retry/my-test?succeedAfter=2&failStatus=429"
HTTP/1.1 429 Too Many Requests
retry-after: 1
x-attempt: 1

$ curl -i "https://api.testingapis.com/api/chaos/retry/my-test?succeedAfter=2&failStatus=429"
HTTP/1.1 429 Too Many Requests
retry-after: 1
x-attempt: 2

$ curl -i "https://api.testingapis.com/api/chaos/retry/my-test?succeedAfter=2&failStatus=429"
HTTP/1.1 200 OK
x-attempt: 3

$ curl -X DELETE https://api.testingapis.com/api/chaos/retry/my-test
{"message":"Counter for 'my-test' reset after 3 attempt(s).","key":"my-test"}
Contoh ini memakai endpoint untuk anggota yang sudah masuk.MasukBuat akun gratis

Berikut tes untuk klien yang melakukan retry, dengan test runner bawaan Node. fetchWithRetry lengkap dengan backoff eksponensial dan dukungan Retry-After ada di pelajaran timeout, retry, dan rate limit (dalam bahasa Inggris).

JavaScript
import { test } from "node:test";
import assert from "node:assert/strict";
import { fetchWithRetry } from "./client.js"; // your code under test

test("retries a 503 and returns the eventual 200", async () => {
  const key = `ci-${Date.now()}`;
  const res = await fetchWithRetry(
    `https://api.testingapis.com/api/chaos/retry/${key}?succeedAfter=2`,
  );
  assert.equal(res.status, 200);
  assert.equal(res.headers.get("x-attempt"), "3");
});

test("gives up on a 400 without retrying", async () => {
  const res = await fetchWithRetry("https://api.testingapis.com/api/status/400");
  assert.equal(res.status, 400);
});
Contoh ini memakai endpoint untuk anggota yang sudah masuk.MasukBuat akun gratis

Timeout dan koneksi terputus

Sebagian kegagalan tidak pernah menghasilkan kode status. Klien Anda harus menyadarinya sendiri, dan skrip yang hanya memeriksa res.ok tidak akan pernah melihatnya. Skrip ini memanggil lima endpoint yang gagal dan mencetak apa yang dilakukan fetch pada masing-masing:

failures.mjs
const BASE = "https://api.testingapis.com";

async function attempt(label, url, init) {
  try {
    const res = await fetch(url, init);
    const body = await res.text();
    console.log(label.padEnd(8), res.status, res.headers.get("retry-after") ?? "-", body.slice(0, 50));
  } catch (err) {
    console.log(label.padEnd(8), "threw", err.name, err.cause?.code ?? err.message);
  }
}

await attempt("500", `${BASE}/api/status/500`);
await attempt("429", `${BASE}/api/status/429`);
await attempt("error=", `${BASE}/api/Products/1?error=503`);
await attempt("timeout", `${BASE}/api/chaos/timeout?seconds=10`, { signal: AbortSignal.timeout(2000) });
await attempt("partial", `${BASE}/api/chaos/partial`);
Contoh ini memakai endpoint untuk anggota yang sudah masuk.MasukBuat akun gratis
Output (Node 24)
500      500 - {"status":500,"statusText":"Internal Server Error
429      429 5 {"status":429,"statusText":"Too Many Requests","c
error=   503 - {"status":503,"error":"Service Unavailable","mes
timeout  threw TimeoutError The operation was aborted due to timeout
partial  threw TypeError UND_ERR_SOCKET

Timeout dan body terpotong sama-sama melempar exception alih-alih mengembalikan response. Timeout melempar karena AbortSignal.timeout(2000) menyerah setelah dua detik. Tanpa signal, fetch akan menunggu genap sepuluh detik. Response parsial melempar saat membaca body, setelah status dan header tiba dan tampak sehat. curl melaporkan masalah yang sama:

Terminal
$ curl -sS -o /dev/null https://api.testingapis.com/api/chaos/partial
curl: (18) end of response with 9936 bytes missing
Contoh ini memakai endpoint untuk anggota yang sudah masuk.MasukBuat akun gratis

Rate limiter sungguhan

/api/status/429 memalsukan satu response. /api/RateLimitmasuk untuk melihat adalah limiter fixed-window sungguhan: lima request per 60 detik per klien, dengan X-RateLimit-Remaining yang terus berkurang dan 429 dengan Retry-After yang akurat pada request keenam. Kirim header X-Client-Id agar tes Anda punya jendela sendiri, dan POST /api/RateLimit/resetmasuk untuk melihat mengosongkannya. Referensi rate limit berisi setiap header.

GET/api/RateLimit
Request ini memakai endpoint untuk anggota yang sudah masuk.MasukBuat akun gratis

Yang perlu diperiksa di klien Anda

  • Error 4xx selain 408 dan 429 tidak diulang: request yang buruk tetap buruk.
  • 429 dan 503 menunggu Retry-After alih-alih langsung mencoba lagi.
  • Retry berhenti setelah jumlah percobaan maksimal, dan error terakhir sampai ke pengguna.
  • Setiap request punya timeout, dan timeout menampilkan error, bukan spinner tanpa akhir.
  • Body yang gagal di-parse atau tiba tidak lengkap adalah error, meski statusnya 200.
  • message dari body error ditampilkan atau dicatat, bukan ditelan.