Для запуска интеграционных тестов в Golang часто требуются внешние зависимости в виде базы данных, брокера сообщений либо еще каких-то сторонних компонентов.В итоге для поднятия внешних сервисов мы используем Docker и пишем docker-compose.yml файл который выглядит как-то так:
version: '3' services: db: image: postgres:10.6-alpine ports: - '5432' environment: LC_ALL: C.UTF-8 POSTGRES_DB: test POSTGRES_USER: test POSTGRES_PASSWORD: pass
Далее до запуска go test мы делаем docker-compose up -d.
Все вроде здорово и все работает, но что если мы будем запускать нужные нам контейнеры прямо в наших тестах? А после завершения мы будем все очищать. И все это без yaml и утилиты docker-compose.
Это возможно при помощи библиотеки https://github.com/ory/dockertest
package main import ( "fmt" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "github.com/ory/dockertest" "log" ) func main() { pool, err := dockertest.NewPool("") if err != nil { log.Fatalf("Could not connect to docker pool: %s", err) } // pulls an image, creates a container based on it and runs it resource, err := pool.Run("postgres", "10.6-alpine", []string{"POSTGRES_DB=test", "POSTGRES_USER=test", "POSTGRES_PASSWORD=pass"}) if err != nil { log.Fatalf("Could not start resource: %s", err) } if err := pool.Retry(func() error { var err error dsnString := "postgres://test:[email protected]:" + resource.GetPort("5432/tcp") + "/test?sslmode=disable" db, err := sqlx.Connect("postgres", dsnString) if err != nil { return err } return db.Ping() }); err != nil { log.Printf("Could not connect to docker resource: %s", err) } fmt.Println(" Image port: " + resource.GetPort("5432/tcp")) if err := pool.Purge(resource); err != nil { log.Fatalf("Could not purge resource: %s", err) } }
Что делает наш код? В начале поднимает dockertest pool и запускает нужный нам контейнер при помощи pool.Run:
resource, err := pool.Run("postgres", "10.6-alpine", []string{"POSTGRES_DB=test", "POSTGRES_USER=test", "POSTGRES_PASSWORD=pass"})
Далее наша программа ждет пока контейнер не будет готов к работе при помощи метода pool.Retry и когда все готово просто показывает на каком порту работает наш Postgres:
resource.GetPort("5432/tcp")
Итого данный кусок кода можно поместить в начало и последнюю часть в конец работы наших тестов.