Compartir comentarios
Las respuestas se generan en base a la documentación.

Escribe pruebas con Testcontainers

Ya tienes lista la implementación del Repository, pero para realizar las pruebas necesitas una base de datos PostgreSQL. Puedes usar testcontainers-go para levantar una base de datos Postgres en un contenedor Docker y ejecutar tus pruebas contra esa base de datos.

Configura la base de datos de pruebas

En aplicaciones reales, podrías utilizar una herramienta de migración de bases de datos, pero para esta guía, usaremos un script para inicializar la base de datos.

Crea un archivo testdata/init-db.sql para crear la tabla CUSTOMERS e insertar datos de muestra:

CREATE TABLE IF NOT EXISTS customers (id serial, name varchar(255), email varchar(255));

INSERT INTO customers(name, email) VALUES ('John', '[email protected]');

Entiende la API de testcontainers-go

La biblioteca testcontainers-go proporciona la abstracción genérica Container que puede ejecutar cualquier servicio contenedorizado. Para simplificar aún más, testcontainers-go ofrece módulos específicos para cada tecnología que reducen el código repetitivo y proporcionan un patrón de opciones funcionales para construir la instancia del contenedor.

Por ejemplo, PostgresContainer proporciona WithDatabase(), WithUsername(), WithPassword() y otras funciones para configurar varias propiedades de los contenedores Postgres.

Escribe la prueba

Crea el archivo customer/repo_test.go e implementa la prueba:

package customer

import (
	"context"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/modules/postgres"
)

func TestCustomerRepository(t *testing.T) {
	ctx := context.Background()

	ctr, err := postgres.Run(ctx,
		"postgres:16-alpine",
		postgres.WithInitScripts(filepath.Join("..", "testdata", "init-db.sql")),
		postgres.WithDatabase("test-db"),
		postgres.WithUsername("postgres"),
		postgres.WithPassword("postgres"),
		postgres.BasicWaitStrategies(),
	)
	testcontainers.CleanupContainer(t, ctr)
	require.NoError(t, err)

	connStr, err := ctr.ConnectionString(ctx, "sslmode=disable")
	require.NoError(t, err)

	customerRepo, err := NewRepository(ctx, connStr)
	require.NoError(t, err)

	c, err := customerRepo.CreateCustomer(ctx, Customer{
		Name:  "Henry",
		Email: "[email protected]",
	})
	assert.NoError(t, err)
	assert.NotNil(t, c)

	customer, err := customerRepo.GetCustomerByEmail(ctx, "[email protected]")
	assert.NoError(t, err)
	assert.NotNil(t, customer)
	assert.Equal(t, "Henry", customer.Name)
	assert.Equal(t, "[email protected]", customer.Email)
}

Esto es lo que hace la prueba:

  • Llama a postgres.Run() con la imagen Docker postgres:16-alpine como primer argumento. Esta es la API v0.41.0: la imagen es un parámetro posicional obligatorio en lugar de una opción.
  • Configura scripts de inicialización usando WithInitScripts(...) para que la tabla CUSTOMERS se cree y los datos de muestra se inserten después de que la base de datos se inicie.
  • Usa postgres.BasicWaitStrategies() que combina la espera del mensaje de log de Postgres y la preparación del puerto. Esto reemplaza la configuración manual de la estrategia de espera.
  • Llama a testcontainers.CleanupContainer(t, ctr) justo después de postgres.Run(). Esto registra la limpieza automática con el framework de pruebas, reemplazando el patrón manual de t.Cleanup y Terminate.
  • Obtiene la cadena de conexión ConnectionString del contenedor e inicializa un Repository.
  • Crea un cliente con el correo electrónico [email protected] y verifica que el cliente exista en la base de datos.