Testing con MongoDB: integración, datos y concurrencia | Nicolás Garzón
Inicio Wiki MongoDB Testing Volver a MongoDBMongoDB
Testing Explica cómo probar lógica y persistencia MongoDB con bases aisladas, fixtures, transacciones, índices, concurrencia y entornos reproducibles.
Última actualización Actualizada 25 de jul de 2026
El testing de una aplicación con MongoDB debe cubrir tanto la lógica del dominio como la semántica real del servidor. Los mocks ayudan a aislar servicios, pero no validan BSON, índices, aggregations, transactions, write concerns ni errores reales.
Nota anteriorRepositories y acceso a datos Nota siguiente MongoDB en Docker Texto
Copiar unit tests
→ reglas puras
integration tests
→ driver/ODM + MongoDB real
end-to-end tests
→ API + autenticación + base + infraestructuraUna estrategia completa combina los tres niveles.
validación y normalización;
cálculos;
decisiones de negocio;
mappers y DTOs;
construcción de updates;
manejo de errores traducidos.
TypeScript
Copiar expect ( calculateOrderTotal ( items) ) . toEqual ( '18500.00' ) ; No necesitas MongoDB para probar una función pura.
Validan repositories y Models contra un servidor real:
TypeScript
Copiar it ( 'prevents duplicate SKU per business' , async ( ) => {
await products. insertOne ( { businessId, sku: 'A-1' } ) ;
await expect (
products. insertOne ( { businessId, sku: 'A-1' } )
) . rejects. toMatchObject ( { code: 11000 } ) ;
} ) ; Esto comprueba el índice unique, no una simulación.
Un mock puede devolver cualquier resultado que programes y no reproduce:
casting de BSON;
null frente a missing;
query planner;
collation;
multikey indexes;
duplicate key;
transactions;
write conflicts;
aggregation stages;
timeouts y failover.
Úsalo para probar coordinación, no para demostrar que una query funciona.
Una imagen oficial o entorno efímero ofrece reproducibilidad. Fija la versión:
YAML
Copiar services :
mongo :
image : mongo: 8.0 No uses latest. Prueba también la versión objetivo de producción y, durante upgrades, la versión origen.
Transactions, Change Streams y retryable behavior requieren replica set:
Texto
Copiar mongod --replSet rs0
→ rs.initiate()Un servidor standalone puede hacer pasar tests que fallarán cuando el código utilice sessions o streams.
base única por worker;
prefijo por test suite;
collections limpiadas entre casos;
transactions para rollback cuando sean compatibles;
database efímera por ejecución.
Evita que pruebas paralelas compartan IDs o dependan del orden.
Los fixtures deben ser mínimos y explícitos:
TypeScript
Copiar await seedOrder ( {
businessId,
status: 'pending' ,
items: 2
} ) ; No cargues un dump enorme como única estrategia. Los tests deben mostrar qué datos importan.
Para pruebas de rendimiento sí usa datasets representativos y distribución realista.
Asegúrate de que el entorno crea los mismos índices y validators que producción. Si Mongoose usa autoIndex en tests pero producción usa migrations, los tests pueden validar una configuración distinta.
Incluye un test de drift:
índices esperados;
nombres;
opciones unique/partial/collation;
validators;
collection options.
Para hot paths, ejecuta explain en tests de integración o performance:
TypeScript
Copiar const plan = await orders. find ( filter)
. sort ( sort)
. limit ( 20 )
. explain ( 'executionStats' ) ; No hagas assertions demasiado rígidas sobre toda la estructura del plan, porque puede cambiar entre versiones. Comprueba invariantes útiles: ausencia de COLLSCAN, límites de docs examined o índice esperado cuando sea contractual.
TypeScript
Copiar await Promise . allSettled ( [
reserveStock ( input) ,
reserveStock ( input)
] ) ; Verifica que stock no quede negativo y que una operación falle por precondition. Ejecutar funciones secuencialmente no demuestra seguridad concurrente.
commit exitoso;
abort por error;
session omitida accidentalmente;
retry del callback;
unknown commit result;
efectos externos no duplicados.
El callback debe tolerar reejecución.
Prueba con replica set y timeouts. Guarda resume token y simula reinicio del consumidor. No hagas tests que esperen indefinidamente; usa AbortSignal o límites claros.
Verifica rutas diferentes:
save();
updateOne();
findOneAndUpdate();
bulkWrite;
lean;
populate;
middleware;
validators de update.
Un test de save() no cubre el resto.
Crea datos de dos negocios y prueba que cada repository:
solo devuelve su tenant;
no actualiza otro tenant;
no filtra después de leer;
aplica scope en aggregations y populate;
ignora businessId malicioso del request.
Estos tests deben existir para cada caso de acceso crítico.
Prueba ObjectId, Date, Decimal128, Long y Binary. Comprueba DTOs y JSON:
TypeScript
Copiar expect ( dto. total) . toBe ( '18500.00' ) ;
expect ( dto. id) . toBe ( orderId. toString ( ) ) ; No dejes que snapshots oculten conversiones incorrectas.
primary election;
network interruption;
pool saturation;
timeout;
duplicate key;
disk o quota en staging;
shutdown durante una operación;
restore con schema anterior.
No todo pertenece al pipeline de cada commit; algunos son ejercicios periódicos.
volumen representativo;
concurrencia;
distribución y tenants outlier;
cold/warm cache;
reads y writes mezclados;
p95/p99;
pool wait;
replication lag.
Una prueba con cien documentos no valida índices de producción.
iniciar MongoDB;
configurar replica set si hace falta;
aplicar migrations e índices;
ejecutar tests;
guardar logs ante fallo;
destruir recursos.
Usa readiness real, no un sleep fijo.
No uses dumps de producción sin anonimización. Los fixtures no deben contener PII real, tokens ni secretos.
tests pasan por orden accidental;
limpieza falla y deja datos;
clock/timezone cambia resultados;
replica set aún no tiene primary;
index build no terminó;
tests paralelos comparten database;
mock acepta una query inválida;
retry duplica un side effect.
probar solo services mockeados;
usar standalone para transactions;
depender de latest;
no crear índices reales;
tests de tenant con un solo tenant;
fixtures gigantes y opacos;
no probar concurrencia;
asserts frágiles de explain;
usar datos de producción sin protección.
Clasifica unit/integration/e2e.
Ejecuta contra MongoDB real.
Alinea versión e índices.
Prueba dos tenants.
Simula carreras.
Prueba transactions y streams.
Valida BSON/DTO.
Introduce fallos.
Mide hot paths.
Revisa flakiness y aislamiento.
Los tests útiles prueban la capa correcta. La lógica pura puede aislarse; queries, índices, BSON y concurrencia necesitan MongoDB real. Un entorno reproducible con replica set, datos aislados y migrations reales evita una confianza falsa basada en mocks.
Comprueba lo aprendido
¿Qué valida un integration test?
¿Por qué un mock no prueba duplicate key?
¿Cuándo necesitas replica set?
¿Cómo probarías tenant isolation?
¿Qué carrera simularías en inventario?
¿Qué debe hacer CI antes de los tests?