Por Lucas Yoris · Performate
Mocks vs dependencias reales en pruebas de carga: un punto medio pragmático
Mocks vs deps reales en pruebas de carga: riesgos de virtualización estilo WireMock, brechas de fidelidad y cuándo golpear sandboxes—evidencia de rendimiento honesta.
El informe de load test mostró p99 espectacular—porque el proveedor de pagos era WireMock en localhost con 5 ms fijos. Finanzas preguntó por capacidad para Black Friday; el gráfico no era mentira deliberada, pero faltaba la brecha de fidelidad al lado del chart, y eso es lo que convierte virtualización en riesgo de negocio.
Mocks vs dependencias reales en pruebas de carga no es ideología «todo real» vs «todo mock». Es un portafolio: contratos para velocidad, sandboxes para colas reales, e inyección de latencia cuando necesitas soak sin quemar presupuesto de vendor. En esta guía verás reglas pragmáticas, cómo documentar gaps, y cómo organizar escenarios duales en k6 sin explosionar repos.
Por qué los mocks aceleran y mienten (a la vez)
Los mocks y servicios virtuales (WireMock y similares) comprimen calendarios:
- Paridad funcional para CI sin esperar sandbox de terceros.
- Escenarios de error repetibles (429, timeouts) sin dañar prod.
Pero ocultan:
- Colas de latencia reales y tails que importan al SLO.
- Rate limits contractuales del vendor—tu mock no factura RPM.
- Comportamiento de cold start en APIs serverless del proveedor.
- Drift de contrato cuando el mock no se actualiza con el OpenAPI real.
Los sandboxes de terceros también difieren de producción—ver dependencias de APIs de terceros. La honestidad del informe está en documentar qué track corrió, no en pretender que un gráfico lo resume todo.
Cuando staging full-stack es demasiado caro o frágil
No siempre puedes golpear Visa, Salesforce o un LLM vendor a escala. El punto medio es dual-track: mismo script k6, distinto BASE_URL o perfil DEP_TRACK=mock|sandbox|integrated.
Reglas pragmáticas: tres tracks
| Track | Cuándo | Qué demuestra |
|---|---|---|
| Contrato / mock | CI rápido, rutas de error | Lógica, auth, routing interno |
| Sandbox vendor | Ventanas acordadas, RPM limitado | Colas, 429, formas de timeout reales |
| Soak integrado | Pre-launch, bajo aprobación | Tails, fugas, interacción multi-servicio |
Añade inyección de latencia downstream en mocks para soak cuando no hay sandbox—latencia sintética pero documentada, mejor que 5 ms planos eternos.
Combina con staging vs producción en pruebas de carga: el track mock no sustituye evidencia de entorno cercano a prod cuando el riesgo lo exige.
Implementación con k6: perfiles mock vs integrado
Script de ejemplo (ilustrativo).
Qué demuestra este ejemplo:
DEP_TRACKelige URL de mock WireMock vs sandbox real.- Umbrales distintos por track—no compares
p99mock con sandbox en la misma tabla sin etiqueta. - Tags
dep:paymentspara métricas claras.
import http from 'k6/http';
import { check, sleep } from 'k6';
const TRACK = __ENV.DEP_TRACK || 'mock'; // mock | sandbox
const endpoints = {
mock: 'https://wiremock.internal:8080/payments',
sandbox: 'https://sandbox.payments-vendor.com/v1/charges',
};
const BASE = endpoints[TRACK];
export const options = {
scenarios: {
checkout_pay: {
executor: 'constant-arrival-rate',
rate: Number(__ENV.RPS || 10),
timeUnit: '1s',
duration: '5m',
preAllocatedVUs: 15,
maxVUs: 60,
exec: 'pay',
},
},
thresholds: {
http_req_failed: ['rate<0.01'],
'http_req_duration{dep:payments}': [
TRACK === 'mock' ? 'p(95)<200' : 'p(95)<900',
],
},
};
export function pay() {
const res = http.post(
`${BASE}/charge`,
JSON.stringify({ amount: 1000, currency: 'USD' }),
{
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${__ENV.VENDOR_TOKEN}` },
tags: { dep: 'payments', track: TRACK },
},
);
check(res, { 'charge ok': (r) => r.status >= 200 && r.status < 300 });
sleep(0.3);
}
Patrones que funcionan
- README del escenario lista brecha de fidelidad («mock: sin 429, sin tail de 2s»).
- Canary contra sandbox dentro de RPM contractual—not sorpresa.
- Mismo journey en tracks distintos—diff de métricas, no journeys incomparables.
- Taxonomía de errores cuando mezclas timeouts de mock con 5xx reales.
Anti-patrones
- Un solo número de
p99en slide ejecutivo sin etiqueta de track. - Mock sin actualizar cuando cambia OpenAPI del vendor.
- Soak full-scale contra sandbox sin aprobación legal/financiera.
Marco de decisión: mock, sandbox o integrado
| Situación | Acción |
|---|---|
| Gate CI pre-merge | Mock o stub + umbrales estrictos de error |
| Validar colas y 429 | Sandbox con RPS acotado |
| Sign-off de launch | Integrado o sandbox + soak documentado |
| Vendor sin sandbox | Mock + latencia inyectada + disclaimer en informe |
| Microservicio aislado | Mock downstream; carga real en servicio bajo test |
Usa mock si necesitas velocidad y control de errores—no si afirmas capacidad de peak day sin otro track.
Usa sandbox si la pregunta incluye rate limits y tails—respeta contrato.
Usa integrado/soak si el riesgo justifica costo y coordinación—planificación de capacidad.
Checklist de honestidad en el informe
- ¿Título del run incluye
track=mock|sandbox|integrated? - ¿Párrafo de brechas de fidelidad junto al gráfico principal?
- ¿RPM y ventana de sandbox documentados?
- ¿Finanzas/negocio sabe qué afirmación se hace con cada track?
- ¿Escenarios duales en un repo, no forks silenciosos?
Cómo Performate organiza dual-track sin explosionar repos
Las explosiones de forks ocurren cuando paths mock e integrados viven en repos separados. Abajo hay un ejemplo concreto de flujo para checkout + dependencia payments que usa este artículo.
Ejemplo: smoke mock en CI y sandbox nightly en un workspace
- Importa colección checkout con dependencia payments parametrizada como variable de colección
paymentsBase. Problema resuelto: una definición de request; cambia target por perfil. - Crea perfil de entorno
ci_mockapuntandopaymentsBasea URL interna WireMock; define arrival rate bajo. Problema resuelto: gate rápido en PR sin gasto de vendor. - Crea perfil
nightly_sandboxcon URL sandbox del vendor y rate acotado por RPM. Problema resuelto: verdad programada sin editar código de executor a mano. - Etiqueta escenarios
dep:mockydep:sandboxpara reportes filtrados. Problema resuelto: comparación lado a lado en un export. - Añade parámetro de delay mock en headers de escenario o equivalente de pre-request script antes de exportar. Problema resuelto: inyecta latencia downstream sin abandonar mocks del todo.
- Exporta script k6 con
__ENV.PAYMENTS_URLyDEP_MODEpara paridad de pipeline. Problema resuelto: iteración en UI y jobs CI/nightly siguen alineados.
Ese flujo conecta directamente con el cta de este post: simplificar pruebas de carga k6 desde imports hasta resultados para que equipos publiquen confianza de rendimiento más rápido—sin fingir que mocks son producción.
Cierre
Los mocks son herramientas—not evidencia universal. La práctica madura corre varios tracks, documenta brechas al lado de cada gráfico, y reserva afirmaciones de capacidad para sandboxes o integraciones aprobadas.
Etiqueta tu próximo informe con el track en el título y añade tres líneas de brecha de fidelidad antes de enviarlo a stakeholders—eso cuesta minutos y evita decisiones de millones sobre colas que el mock nunca mostró.
¿Listo para optimizar el rendimiento de tu API?
Explora cómo Performate simplifica las pruebas de carga con k6, desde imports hasta resultados, para que tu equipo publique con más confianza en rendimiento.