Integration Testing Go with Docker: From A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Integration Testing Go with Docker: Complete Guide

\n\n

Integration testing is a critically important stage of development, especially in the world of microservices and distributed systems. Go (Golang) combined with Docker provides powerful and elegant tools for creating reliable integration tests. In this article, we will break down how to set up the environment, write tests for interacting with databases and external services using Docker, testcontainers-go, and the standard testing library.

\n\n

1. Why Docker for Integration Testing?

\n\n

Traditional unit tests isolate logic but do not verify interaction with real dependencies: databases, queues, APIs. Docker solves this problem by allowing:

\n
    \n
  • Environment Isolation: Each test runs a clean container, eliminating state conflicts.
  • \n
  • Repeatability: Identical environment on the local machine and in CI/CD.
  • \n
  • Fast Deployment: Containers start in seconds.
  • \n
  • Easy Cleanup: The container is destroyed after the test.
  • \n
\n\n

We will use the testcontainers-go library — it provides a high-level API for managing the container lifecycle directly from the test code.

\n\n

2. Project Setup and Dependency Installation

\n\n

Let's create a simple HTTP server in Go that saves data to PostgreSQL. Then we'll write an integration test that checks the endpoint.

\n\n

Project Structure:

\n
myapp/\n├── main.go\n├── go.mod\n├── go.sum\n├── handlers/\n│   └── user.go\n└── integration_test.go
\n\n

Step 1: Initialize the module and install testcontainers:

\n
go 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\n

Step 2: Write a simple handler in handlers/user.go:

\n
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\n

3. Writing the Integration Test with Docker

\n\n

Now for the interesting part — a test that spins up PostgreSQL in Docker, creates a table, starts our server, and verifies its operation.

\n\n

File integration_test.go:

\n
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. Start PostgreSQL container\n    pgContainer, err := postgres.RunContainer(ctx,\n        testcontainers.WithImage("postgres:15-alpine"),\n        postgres.WithDatabase("testdb"),\n        postgres.WithUsername("test"),\n        postgres.                

Blogs

Book Recommendations