tutoriales.com

Pruebas de Integración en GraphQL: Asegurando la Calidad con SuperTest y Jest

Este tutorial completo guía al desarrollador en la implementación de pruebas de integración para APIs GraphQL. Descubrirás cómo configurar un entorno de pruebas con Jest y SuperTest, simular consultas y mutaciones, y validar respuestas complejas de manera automatizada.

Intermedio8 min de lectura5 views
Reportar error

Introducción a las Pruebas de Integración en GraphQL 🧪

Desarrollar una API con GraphQL nos otorga una flexibilidad increíble, permitiendo a los clientes solicitar exactamente los datos que necesitan. Sin embargo, esta misma flexibilidad puede convertir el mantenimiento y la validación en un desafío considerable. ¿Cómo aseguramos que nuestros resolvers, esquemas y conexiones a bases de datos funcionen de manera armónica sin romper nada en producción?

La respuesta son las pruebas de integración. A diferencia de las pruebas unitarias que aíslan componentes individuales, las pruebas de integración evalúan el sistema completo, desde el punto de entrada HTTP hasta la capa de datos. En este tutorial, exploraremos cómo construir una suite de pruebas profesional utilizando Jest y SuperTest sobre una API GraphQL en Node.js.

💡 Consejo: Tener una sólida batería de pruebas de integración te da la confianza absoluta para refactorizar esquemas y optimizar resolvers sin temor a introducir regresiones inesperadas.

🛠️ Configuración del Entorno de Pruebas

Para poner en marcha nuestro entorno, necesitamos instalar las dependencias necesarias. Asegúrate de tener Node.js instalado en tu sistema y un proyecto GraphQL básico configurado. Utilizaremos Intermedio como nivel de referencia para este recorrido.

Dependencias Esenciales

Ejecuta el siguiente comando en tu terminal para instalar las herramientas de testing:

npm install --save-dev jest supertest @types/jest

Una vez instaladas, configuraremos nuestro archivo jest.config.js para manejar correctamente la transpilación y la cobertura de código. A continuación, un ejemplo de configuración básica:

module.exports = {
  testEnvironment: 'node',
  verbose: true,
  coveragePathIgnorePatterns: ['/node_modules/'],
}; 

🏗️ Arquitectura de la Suite de Pruebas

Antes de escribir código, es vital entender cómo interactúan los componentes durante una prueba de integración HTTP. SuperTest se encarga de realizar peticiones reales (o simuladas en memoria) contra nuestra aplicación Express que aloja el servidor GraphQL.

Arquitectura de Pruebas GraphQL Cliente de Test (Jest / SuperTest) Servidor Express Esquema y Resolvers Base de Datos Entorno de Pruebas HTTP POST (GraphQL Query) JSON Response Consultas Flujo de Ejecución de Pruebas de Integración
Paso 1: Inicializar la aplicación Express y el servidor Apollo en modo de pruebas.
Paso 2: Configurar una base de datos temporal (en memoria o SQLite) para cada ciclo de tests.
Paso 3: Ejecutar consultas y mutaciones mediante peticiones HTTP POST con SuperTest.
Paso 4: Aserciones de los resultados obtenidos contra los datos esperados usando Jest.

✍️ Escribiendo Nuestra Primera Prueba de Consulta (Query)

Vamos a suponer que tenemos una API de gestión de usuarios. Queremos probar que la consulta getUsers devuelve la lista correcta de usuarios registrados.

Crea un archivo llamado user.test.js e implementa la siguiente estructura:

const request = require('supertest');
const app = require('../src/app'); // Tu aplicación Express configurada

describe('GraphQL User Queries', () => {
  it('debería retornar una lista de usuarios', async () => {
    const queryData = {
      query: `
        query {
          getUsers {
            id
            name
            email
          }
        }
      `
    };

    const response = await request(app)
      .post('/graphql')
      .send(queryData);

    expect(response.status).toBe(200);
    expect(response.body.errors).toBeUndefined();
    expect(response.body.data.getUsers).toBeInstanceOf(Array);
    expect(response.body.data.getUsers.length).toBeGreaterThan(0);
  });
});
⚠️ Advertencia: Evita utilizar la misma base de datos de producción para las pruebas. Utiliza siempre una base de datos aislada o en memoria para evitar corromper datos reales.

⚡ Probando Mutaciones y Manejo de Errores

Las mutaciones modifican el estado del servidor, por lo que su prueba requiere verificar tanto el éxito de la operación como la correcta gestión de errores cuando enviamos datos inválidos.

Prueba de Mutación Exitosa

describe('GraphQL User Mutations', () => {
  it('debería crear un nuevo usuario exitosamente', async () => {
    const mutationData = {
      query: `
        mutation {
          createUser(input: { name: "Ana Pérez", email: "ana@example.com" }) {
            id
            name
            email
          }
        }
      `
    };

    const response = await request(app)
      .post('/graphql')
      .send(mutationData);

    expect(response.status).toBe(200);
    expect(response.body.data.createUser).toHaveProperty('id');
    expect(response.body.data.createUser.name).toBe('Ana Pérez');
  });
});

Validación de Errores en GraphQL

Una gran ventaja de GraphQL es que un error de validación o lógica suele devolver un código HTTP 200 OK, pero con una propiedad errors en el cuerpo JSON. Nuestras pruebas deben reflejar este comportamiento:

  it('debería retornar un error si el email ya está registrado', async () => {
    const mutationData = {
      query: `
        mutation {
          createUser(input: { name: "Duplicado", email: "ana@example.com" }) {
            id
          }
        }
      `
    };

    const response = await request(app)
      .post('/graphql')
      .send(mutationData);

    expect(response.status).toBe(200);
    expect(response.body.errors).toBeDefined();
    expect(response.body.errors[0].message).toContain('correo ya existe');
  });

📊 Comparativa: Pruebas Unitarias vs Pruebas de Integración en GraphQL

Para entender el valor de lo que estamos construyendo, analicemos las diferencias clave entre ambos enfoques:

CaracterísticaPruebas Unitarias (Resolvers aislados)Pruebas de Integración (SuperTest + Jest)
AlcanceUna función resolver individualTodo el flujo HTTP, esquema y base de datos
VelocidadExtremadamente rápidasLigeramente más lentas por E/S
Detección de erroresLógica interna del resolverProblemas de esquema, serialización y red
MantenimientoAlto si se cambian mocksBajo, valida el comportamiento real del API

🔍 Preguntas Frecuentes (FAQ)

¿Cómo manejo la autenticación en las pruebas de integración? Puedes simular cabeceras de autorización HTTP utilizando el método .set() de SuperTest. Por ejemplo: request(app).post('/graphql').set('Authorization', 'Bearer token_falso').send(...).
¿Es necesario reiniciar la base de datos entre cada prueba? Sí, es altamente recomendable utilizar ganchos como beforeEach o afterEach de Jest para limpiar las tablas o colecciones de la base de datos de prueba y garantizar la idempotencia.

Conclusión y Próximos Pasos 🎯

Implementar pruebas de integración con Jest y SuperTest es un pilar fundamental para mantener la robustez de cualquier API GraphQL a medida que evoluciona. Al simular peticiones HTTP reales y validar tanto los datos devueltos como los errores esperados, te aseguras de ofrecer un servicio confiable a tus clientes.

Como siguientes pasos, te sugiero explorar la automatización de estas pruebas dentro de tu tubería de integración continua (CI/CD) usando GitHub Actions o GitLab CI.

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!