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 Dockerpostgres:16-alpinecomo 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 tablaCUSTOMERSse 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 depostgres.Run(). Esto registra la limpieza automática con el framework de pruebas, reemplazando el patrón manual det.CleanupyTerminate. - Obtiene la cadena de conexión
ConnectionStringdel contenedor e inicializa unRepository. - Crea un cliente con el correo electrónico
[email protected]y verifica que el cliente exista en la base de datos.