Skip to main content
Volver al blog Copiar Markdown
· 7 min de lectura ·
nextjs vercel testing ci-cd vitest react

Infierno en Vercel CI: Arregla Tests de Next.js Fallando

¿Tus tests pasan en local pero fallan en Vercel? El arreglo es una línea: NODE_ENV en vitest.config.ts, más timeouts para CI. 4 horas perdidas, resumidas. →

Óscar Gallego

Óscar Gallego

Desarrollador Web

Tests passing locally but failing in Vercel CI environment
En este artículo

¿Por qué mis tests pasan en local pero fallan en Vercel?

Cuando los tests funcionan en tu máquina pero mueren en el CI de Vercel, suelen ser dos diferencias de entorno: una configuración incorrecta de NODE_ENV y timeouts pensados para hardware 5-10 veces más rápido que el contenedor del CI.

La checklist rápida:

  1. Fuerza NODE_ENV a 'test'. Tu vitest.config.ts necesita env: { NODE_ENV: 'test' }. Vercel puede usar el modo de producción por defecto, lo que elimina utilidades de testing de React.
  2. Sube los timeouts para CI. El CI de Vercel es 5-10 veces más lento que una máquina local. Haz los timeouts conscientes del entorno: const TIMEOUT = process.env.CI ? 10000 : 5000;.
  3. Lee los logs de Vercel. Busca los tests concretos que fallan o se arrastran. El error actImplementation is not a function suele ser un síntoma del problema de NODE_ENV.
  4. Mockea las operaciones pesadas. Nada de I/O de archivos ni datos gigantes en los tests. Mocks ligeros.
  5. No culpes a las librerías todavía. Antes de pensar en problemas de compatibilidad entre versiones, revisa la configuración del entorno. Es la causa más común.

El resto del post es cómo aprendí cada uno de esos puntos por el camino lento.

Mismo código, mismas dependencias, resultados diferentes

# Local
$ pnpm test
 Todos los tests pasan (181 pasados)

# Vercel
 Build fallido
Error: actImplementation is not a function

Stack: Next.js 16, React 19, Vitest, Vercel Tiempo perdido: 4 horas persiguiendo el problema equivocado Causa raíz: malentender el entorno CI de Vercel

Lo que pensé que era (la parte vergonzosa)

“¡Problema de compatibilidad de React 19 con Testing Library!”

Así que construí, por este orden:

  • un script de parcheo de 125 líneas para internals de React
  • un plugin de Vite personalizado para resolución de módulos
  • archivos mock y redirecciones de imports

Todo falló en Vercel. Todo era innecesario. Cuatro horas de ingeniería muy segura de sí misma, apuntando a un problema que no existía.

El problema real

Tu máquina no es el CI de Vercel

Desarrollo local:

  • SSD rápido, I/O directo
  • CPU/memoria dedicada
  • React se carga en modo desarrollo
  • Entorno consistente

CI de Vercel:

  • Almacenamiento en red (I/O más lento)
  • Recursos de contenedor compartidos
  • Puede usar modo producción por defecto
  • Arranques en frío en cada build

El resultado: las operaciones tardan 5-10x más en Vercel.

Los dos problemas de verdad

Problema 1: el modo de entorno

Vercel no estaba cargando React en modo test por defecto.

La solución:

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',

    // ← Fuerza el modo test de React
    env: {
      NODE_ENV: 'test',
    },
  },
})

Por qué importa: el build de desarrollo de React incluye utilidades de test, y el build de producción las elimina. Sin NODE_ENV: 'test', React se carga incorrectamente en Vercel.

Problema 2: restricciones de recursos

Los contenedores de CI son más lentos. Operaciones que parecen instantáneas en local hacen timeout en Vercel.

La solución:

// Configuración de timeout consciente del CI
const TIMEOUT = process.env.CI ? 10000 : 5000

it('test intensivo en recursos', async () => {
  // código del test
}, TIMEOUT)

Una medición real de esta sesión de depuración:

// Creando un archivo de test de 100MB
const largeFile = createMockImageFile(
  'large.jpg',
  100 * 1024 * 1024,
  'image/jpeg'
)

// Local: ~500ms
// Vercel CI: ~6-7 segundos (!)

La configuración mínima que funciona

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [tsconfigPaths(), react()],
  test: {
    environment: 'jsdom',
    setupFiles: ['./src/test/setup.ts'],
    globals: true,
    css: true,

    // Crítico para CI de Vercel
    env: {
      NODE_ENV: 'test',
    },

    // Timeout global con conciencia de CI
    testTimeout: process.env.CI ? 10000 : 5000,
  },
})

Timeouts de test conscientes del entorno

// test-config.ts
export const TEST_TIMEOUTS = {
  FAST: process.env.CI ? 5000 : 2000,
  MEDIUM: process.env.CI ? 10000 : 5000,
  SLOW: process.env.CI ? 30000 : 15000,
}

// En tus tests
import { TEST_TIMEOUTS } from './test-config'

describe('Feature', () => {
  it('operación rápida', async () => {
    // Test unitario rápido
  }, TEST_TIMEOUTS.FAST)

  it('operación de I/O de archivos', async () => {
    // Procesamiento de archivos, datos pequeños
  }, TEST_TIMEOUTS.MEDIUM)

  it('operación compleja', async () => {
    // Archivos grandes, red, procesamiento pesado
  }, TEST_TIMEOUTS.SLOW)
})

La checklist de diagnóstico para la próxima vez

Cuando los tests fallan en Vercel pero pasan en local:

  1. Comprueba que NODE_ENV: 'test' está configurado en vitest.config
  2. Lee los logs de build de Vercel buscando tests lentos
  3. Añade timeouts explícitos a los tests intensivos en recursos
  4. Usa configuración consciente del entorno
  5. Mockea las operaciones costosas (I/O de archivos, datos grandes)
  6. No empieces asumiendo que es incompatibilidad de librerías

Patrones comunes

// ❌ Asume entorno local
it('test', async () => {
  await heavyOperation()
})

// ✅ Considera diferencias de CI
it('test', async () => {
  await heavyOperation()
}, process.env.CI ? 15000 : 5000)
// ❌ Creando archivos reales de 100MB
const largeFile = createRealFile(100 * 1024 * 1024)

// ✅ Usa mocks ligeros
const largeFile = createMockFile({ size: 100 * 1024 * 1024 })

Lo que me enseñaron cuatro horas perdidas

1. El CI de Vercel no es tu MacBook

Diseña los tests con el CI en mente desde el principio: builds containerizados, recursos compartidos, I/O más lento, defaults diferentes.

2. Configura explícitamente

No confíes en el comportamiento por defecto. Configura NODE_ENV explícitamente, pon timeouts a las operaciones lentas, haz las configuraciones conscientes del entorno.

3. Los mensajes de error pueden engañar

actImplementation is not a function parecía un problema de compatibilidad de React. La causa real: React cargándose en el modo incorrecto por una mala configuración del entorno.

4. Diseña para CI desde el inicio

Escribe los tests sabiendo que se ejecutarán en infraestructura más lenta. Cuenta con arranques en frío de contenedores, almacenamiento en red, throttling de recursos y CPU y memoria compartidas.

Qué hace diferente al entorno de build de Vercel

Builds containerizados. Cada build se ejecuta en un contenedor aislado. Los contenedores comparten recursos de infraestructura y el I/O es en red, no local.

Arranques en frío. Los contenedores se inician frescos en cada build. Sin caché de filesystem caliente, dependencias descargadas cada vez.

Límites de recursos. Throttling de CPU/memoria, infraestructura compartida, características de rendimiento diferentes.

Variables de entorno. Defaults diferentes a tu .env local. NODE_ENV puede no ser lo que esperas, así que configúralo explícitamente.

Configúralo. No luches contra él.

El CI de Vercel es más lento que tu máquina (5-10x), ejecuta Node.js de otra manera y necesita configuración explícita para portarse bien.

El mensaje de error apuntaba a React. El problema era el entorno de Vercel. Saber distinguirlos es todo el arreglo, y es un cambio de una línea en la config una vez que dejas de parchear los internals de React.

Fuentes

Lectura relacionada: otra tarde perdida porque una herramienta ignoraba mi configuración en silencio: el content.config.ts mal colocado que se comió mis campos de schema en Astro.


P.D. ¿Has librado tu propia batalla con el CI de Vercel? Cuéntame qué decía el mensaje de error y cuál era el problema de verdad, en Twitter/X.

Comparte este artículo