example-petstore.com

Dominio de ejemplo · No es un servicio activo · Las visitas desde el navegador muestran esta página · Las solicitudes a la API reciben 410 Gone

Guía · Pruebas

Prueba con una API simulada (mock), no con una dirección de ejemplo

El código que apunta a una dirección inventada como api.example-petstore.com sigue enviando solicitudes reales, y llegan a quien sea dueño de ese nombre. Una API simulada (mock) ofrece la misma comodidad sin ese riesgo: se ejecuta en tu propio equipo o en tus pruebas, responde al instante y siempre devuelve los datos que esperas.

Por qué no una dirección de ejemplo

  • Una dirección de ejemplo que parece un dominio real puede estar registrada por otra persona. Cada solicitud, incluidas las cabeceras con claves o tokens, llega entonces a su servidor.
  • Los nombres sin usar bajo example.com, como api.example.com, no se resuelven en absoluto, así que el código falla con un tiempo de espera agotado o un error de DNS en lugar de mostrar cómo maneja respuestas reales.
  • Las pruebas que dependen de un servidor público son lentas e inestables, y se rompen cuando ese servidor cambia.

Una API simulada (mock) resuelve los tres problemas: escucha en localhost o dentro del proceso de pruebas, y nada sale de tu equipo.

Qué herramienta y cuándo

HerramientaIdeal paraSe ejecuta como
PrismTienes una descripción OpenAPI y quieres respuestas que la siganServidor local (Node.js o Docker), puerto 4010
WireMockRespuestas exactas y grabadas, casos de error y retrasos para cualquier lenguajeServidor local (Java o Docker), puerto 8080
MSWJavaScript y TypeScript: desarrollo front-end y pruebas unitariasDentro del navegador o del proceso de pruebas de Node.js
json-serverUna API REST funcional a partir de un solo archivo JSON, para prototiposServidor local (Node.js), puerto 3000

Para la propia API de ejemplo Swagger Petstore, ejecuta la imagen oficial en local; consulta ¿Buscas Swagger Petstore?

Prism: desde un archivo OpenAPI

Prism lee una descripción OpenAPI (o Swagger 2.0) y responde a cada operación que contiene con los ejemplos o esquemas de ese archivo. Las solicitudes que no coinciden con la descripción reciben un error de validación claro, lo que resulta útil para comprobar un cliente antes de que exista la API real.

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

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

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

La cabecera Prefer elige una respuesta concreta de la descripción, como un código de error o un ejemplo con nombre. Con --dynamic (-d), Prism genera datos nuevos a partir de los esquemas en cada solicitud.

WireMock: respuestas grabadas

WireMock responde a partir de archivos de stubs que escribes o grabas. Sirve para cualquier lenguaje y puede simular respuestas lentas y fallos que un servicio real rara vez produce a demanda.

# 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" }
  }
}

# Arráncalo con la carpeta que contiene mappings/ (y __files/ para cuerpos más grandes)
docker run -it --rm -p 8080:8080 -v "$(pwd)/mocks":/home/wiremock wiremock/wiremock

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

Añade "fixedDelayMilliseconds": 3000 a una respuesta para probar tiempos de espera, o un estado como 503 para probar reintentos. La API de administración en /__admin permite a las pruebas añadir stubs y comprobar qué solicitudes llegaron.

MSW y mocks en PHP: dentro de tus pruebas

Mock Service Worker intercepta las solicitudes dentro de la propia aplicación: en el navegador mediante un service worker, en Node.js dentro del proceso de pruebas. El código probado sigue llamando a su URL base habitual; no se ejecuta ningún servidor adicional.

// 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 })),
]

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

onUnhandledRequest: 'error' hace que una prueba falle en cuanto el código llama a una dirección sin handler, así que una dirección de ejemplo olvidada aparece al ejecutar las pruebas y no en producción. En el navegador, ejecuta una vez npx msw init public/ e inicia el worker desde msw/browser.

En las pruebas de PHP, el MockHandler de Guzzle hace lo mismo dentro del proceso de pruebas, y Symfony tiene MockHttpClient:

// PHP, Guzzle: respuestas en orden, sin red
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/'
);

La dirección de los handlers es api.example.com: un nombre reservado que nunca llega a un servidor real, ni siquiera cuando una solicitud se escapa del mock.

json-server: una API REST rápida

json-server convierte un solo archivo JSON en una API REST con rutas para listar, consultar, crear, actualizar y eliminar. Los cambios se escriben de vuelta en el archivo, lo que resulta práctico para prototipos y demostraciones.

# 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"}'

No tiene validación ni autenticación, así que úsalo solo para prototipos; para pruebas de contrato encajan mejor Prism o WireMock.

Pasar a la API real

Guarda la URL base en la configuración, con el mock como valor para desarrollo y pruebas, y la dirección real solo donde la aplicación se ejecuta de verdad:

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

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

# producción: se define en el entorno de hosting, nunca en el repositorio
API_BASE_URL=https://api.your-real-service.com

Más sobre esto, incluida una comprobación que impide que las direcciones de ejemplo lleguen a producción: Configurar clientes de API y SDK.

Fuentes