API · SDK
Configurar clientes de API y SDK
Mantén las URL base fuera del código, haz que apunten al servicio real y añade una comprobación que impida que las direcciones de ejemplo lleguen a producción.
Guía · Pruebas
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.
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.Una API simulada (mock) resuelve los tres problemas: escucha en localhost o dentro del proceso de pruebas, y nada sale
de tu equipo.
| Herramienta | Ideal para | Se ejecuta como |
|---|---|---|
| Prism | Tienes una descripción OpenAPI y quieres respuestas que la sigan | Servidor local (Node.js o Docker), puerto 4010 |
| WireMock | Respuestas exactas y grabadas, casos de error y retrasos para cualquier lenguaje | Servidor local (Java o Docker), puerto 8080 |
| MSW | JavaScript y TypeScript: desarrollo front-end y pruebas unitarias | Dentro del navegador o del proceso de pruebas de Node.js |
| json-server | Una API REST funcional a partir de un solo archivo JSON, para prototipos | Servidor local (Node.js), puerto 3000 |
Para la propia API de ejemplo Swagger Petstore, ejecuta la imagen oficial en local; consulta ¿Buscas Swagger Petstore?
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 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.
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 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.
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.