Mocks MSW - integración avanzada con Jest, Vitest y Playwright
- MSW
- TDD - Test Driven Development
- MSW Mocks service worker
- Integration tests
🎯 Propósito
Guía práctica y completa para integrar Mock Service Worker (MSW) en entornos de testing modernos — Jest, Vitest y Playwright — cubriendo configuración, estrategias, hooks de ciclo de vida y patrones de validación.
Incluye ejemplos funcionales y referencias cruzadas a TDD patterns.
🧩 Estructura de Mocks Base
Todos los entornos comparten esta base:
src/
├── mocks/
│ ├── handlers.ts
│ ├── browser.ts
│ └── server.ts
├── setupTests.ts
├── app/
└── ...
`
handlers.ts
import { rest } from 'msw';
export const handlers = [
rest.get('/api/user', (req, res, ctx) => {
return res(ctx.status(200), ctx.json({ name: 'Edu', role: 'admin' }));
}),
rest.post('/api/login', (req, res, ctx) => {
const { username } = req.body;
if (username === 'fail') return res(ctx.status(401));
return res(ctx.status(200), ctx.json({ token: 'jwt' }));
}),
];
`
⚙️ Integración con Jest (React, Node)
server.ts
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
jest.setup.ts
import { server } from './src/mocks/server';
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
jest.config.ts
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
testEnvironment: 'jsdom',
✅ Ejemplo de test con mock dinámico
import { fetchUser } from '../api';
test('fetchUser devuelve datos simulados', async () => {
const data = await fetchUser();
expect(data.name).toBe('Edu');
});
🧠 Consejo:
Usa server.use(...) dentro del test para sobrescribir handlers en tiempo real → ver Mocks MSW - patrones y casos reales > Patrón 4 — Fallback de Handlers.
⚡ Integración con Vitest (Vite, React, Svelte, etc.)
Vitest soporta MSW nativamente en modo Node y Browser.
vitest.setup.ts
import { server } from './src/mocks/server';
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
setupFiles: ['./vitest.setup.ts'],
environment: 'jsdom',
},
});
🧪 Ejemplo de test
import { fetchData } from '@/api';
test('mock de login exitoso', async () => {
const result = await fetchData('/api/login', { username: 'ok' });
expect(result.token).toBe('jwt');
});
💡 Usa vi.spyOn(fetch, 'default') o mocks de red nativos si necesitas verificar llamadas de red reales.
🧭 Integración con Playwright (E2E Testing)
MSW puede actuar como proxy de mock para pruebas end-to-end, interceptando fetch y XHR en el navegador real.
Estructura
tests/
├── e2e/
│ ├── example.spec.ts
│ └── playwright.config.ts
└── mocks/
├── browser.ts
├── handlers.ts
└── server.ts
browser.ts
import { setupWorker } from 'msw';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
example.spec.ts
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
window.msw = {};
});
await page.route('**/*', (route, request) => {
if (request.url().includes('/api/user')) {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ name: 'Playwright User' }),
});
} else {
route.continue();
}
});
});
test('renderiza datos mockeados', async ({ page }) => {
await page.goto('http://localhost:5173');
await expect(page.getByText('Playwright User')).toBeVisible();
});
🧭 Opcional: Puedes cargar mockServiceWorker.js directamente en el contexto del navegador para una simulación total de red.
🔄 MSW + CI/CD Integration (GitHub Actions / Docker)
Ejemplo de uso en CI (con Vitest o Jest):
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm test
env:
NODE_ENV: test
📦 En entornos Docker:
- Inicia los mocks con
server.listen()solo siNODE_ENV === 'test'. - Usa
onUnhandledRequest: 'error'para asegurar cobertura completa.
🧠 Estrategias de Testing con MSW
| Estrategia | Entorno | Uso |
|---|---|---|
| Mock Persistente | Dev | Simular backend completo offline |
| Mock Temporal | Jest / Vitest | Sobrescribir handlers por test |
| Mock E2E | Playwright | Validar UX real sin backend |
| Mock Failover | CI | Simular errores de red o auth |
| Mock Condicional | Multi-env | Cambiar respuestas según headers o entorno |
🪶 Mejores Prácticas Globales
- Define nombres consistentes en endpoints (
/api/...). - Resetea handlers tras cada test (
server.resetHandlers()). - Mantén mocks cerca del código fuente (no en repos externos).
- Usa
ctx.delay()para simular condiciones reales. - Documenta tus mocks en la wiki o junto al Glosario de TDD.
- Evita mezclar MSW con interceptores manuales (axios/fetch mocks) en el mismo entorno.
🔗 Referencias
¿Te gusta este contenido? Suscríbete vía RSS