Testes de Integração Go com Docker: guia completo
\n\nTestes de integração são uma etapa criticamente importante do desenvolvimento, especialmente no mundo dos microsserviços e sistemas distribuídos. Go (Golang) em combinação com Docker fornece ferramentas poderosas e elegantes para criar testes de integração confiáveis. Neste artigo, vamos abordar como configurar o ambiente, escrever testes para interação com bancos de dados e serviços externos, usando Docker, testcontainers-go e a biblioteca padrão testing.
1. Por que Docker para testes de integração?
\n\nTestes unitários tradicionais (unit tests) isolam a lógica, mas não verificam a interação com dependências reais: bancos de dados, filas, APIs. O Docker resolve esse problema, permitindo:
\n- \n
- Isolar o ambiente: Cada teste executa um contêiner limpo, eliminando conflitos de estado. \n
- Reprodutibilidade: Ambiente idêntico na máquina local e no CI/CD. \n
- Implantação rápida: Contêineres são iniciados em segundos. \n
- Facilidade de limpeza: Após o teste, o contêiner é destruído. \n
Usaremos a biblioteca testcontainers-go — ela fornece uma API de alto nível para gerenciar o ciclo de vida dos contêineres diretamente do código dos testes.
2. Configuração do projeto e instalação de dependências
\n\nVamos criar um servidor HTTP simples em Go que salva dados no PostgreSQL. Em seguida, escreveremos um teste de integração que verifica o endpoint.
\n\nEstrutura do projeto:
\nmyapp/\n├── main.go\n├── go.mod\n├── go.sum\n├── handlers/\n│ └── user.go\n└── integration_test.go\n\nPasso 1: Inicializamos o módulo e instalamos o testcontainers:
\ngo mod init myapp\ngo get github.com/testcontainers/testcontainers-go\ngo get github.com/testcontainers/testcontainers-go/modules/postgres\ngo get github.com/lib/pq\ngo get github.com/stretchr/testify/assert\n\nPasso 2: Escrevemos um handler simples em handlers/user.go:
package handlers\n\nimport (\n "database/sql"\n "encoding/json"\n "net/http"\n)\n\ntype User struct {\n Name string `json:"name"`\n Age int `json:"age"`\n}\n\nfunc CreateUser(db *sql.DB) http.HandlerFunc {\n return func(w http.ResponseWriter, r *http.Request) {\n var user User\n if err := json.NewDecoder(r.Body).Decode(&user); err != nil {\n http.Error(w, err.Error(), http.StatusBadRequest)\n return\n }\n _, err := db.Exec("INSERT INTO users (name, age) VALUES ($1, $2)", user.Name, user.Age)\n if err != nil {\n http.Error(w, err.Error(), http.StatusInternalServerError)\n return\n }\n w.WriteHeader(http.StatusCreated)\n json.NewEncoder(w).Encode(user)\n }\n}\n\n3. Escrevendo o teste de integração com Docker
\n\nAgora a parte mais interessante — o teste que sobe o PostgreSQL no Docker, cria a tabela, inicia nosso servidor e verifica seu funcionamento.
\n\nArquivo integration_test.go:
package myapp\n\nimport (\n "bytes"\n "context"\n "encoding/json"\n "net/http"\n "net/http/httptest"\n "testing"\n\n "myapp/handlers"\n\n "github.com/lib/pq"\n "github.com/stretchr/testify/assert"\n "github.com/testcontainers/testcontainers-go"\n "github.com/testcontainers/testcontainers-go/modules/postgres"\n "github.com/testcontainers/testcontainers-go/wait"\n)\n\nfunc TestCreateUserIntegration(t *testing.T) {\n ctx := context.Background()\n\n // 1. Iniciamos o contêiner PostgreSQL\n pgContainer, err := postgres.RunContainer(ctx,\n testcontainers.WithImage("postgres:15-alpine"),\n postgres.WithDatabase("testdb"),\n postgres.WithUsername("test"),\n postgres.