Support separate database for testing.

This commit is contained in:
mikestefanello 2021-12-13 12:51:00 -05:00
parent 4e2f186dad
commit 60dedc0944
5 changed files with 65 additions and 34 deletions

View file

@ -2,6 +2,10 @@
pg: pg:
psql postgresql://admin:admin@localhost:5432/app psql postgresql://admin:admin@localhost:5432/app
.PHONY: pg-test
pg-test:
psql postgresql://admin:admin@localhost:5432/app_test
.PHONY: ent-gen .PHONY: ent-gen
ent-gen: ent-gen:
go generate ./ent go generate ./ent

View file

@ -17,6 +17,7 @@ type Env string
const ( const (
EnvLocal Env = "local" EnvLocal Env = "local"
EnvTest Env = "test"
EnvDevelop Env = "dev" EnvDevelop Env = "dev"
EnvStaging Env = "staging" EnvStaging Env = "staging"
EnvQA Env = "qa" EnvQA Env = "qa"
@ -65,6 +66,7 @@ type (
User string `env:"DB_USER,default=admin"` User string `env:"DB_USER,default=admin"`
Password string `env:"DB_PASSWORD,default=admin"` Password string `env:"DB_PASSWORD,default=admin"`
Database string `env:"DB_NAME,default=app"` Database string `env:"DB_NAME,default=app"`
TestDatabase string `env:"DB_NAME_TEST,default=app_test"`
} }
) )

View file

@ -12,6 +12,7 @@ import (
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
_ "github.com/jackc/pgx/v4/stdlib" _ "github.com/jackc/pgx/v4/stdlib"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/labstack/gommon/log"
"goweb/config" "goweb/config"
"goweb/ent" "goweb/ent"
@ -27,33 +28,41 @@ type Container struct {
func NewContainer() *Container { func NewContainer() *Container {
c := new(Container) c := new(Container)
c.initWeb()
c.initConfig() c.initConfig()
c.initWeb()
c.initCache() c.initCache()
c.initDatabase() c.initDatabase()
c.initORM() c.initORM()
return c return c
} }
func (c *Container) initWeb() {
c.Web = echo.New()
}
func (c *Container) initConfig() { func (c *Container) initConfig() {
cfg, err := config.GetConfig() cfg, err := config.GetConfig()
if err != nil { if err != nil {
c.Web.Logger.Fatalf("failed to load configuration: %v", err) panic(fmt.Sprintf("failed to load config: %v", err))
} }
c.Config = &cfg c.Config = &cfg
} }
func (c *Container) initWeb() {
c.Web = echo.New()
// Configure logging
switch c.Config.App.Environment {
case config.EnvProduction:
c.Web.Logger.SetLevel(log.WARN)
default:
c.Web.Logger.SetLevel(log.DEBUG)
}
}
func (c *Container) initCache() { func (c *Container) initCache() {
cacheClient := redis.NewClient(&redis.Options{ cacheClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", c.Config.Cache.Hostname, c.Config.Cache.Port), Addr: fmt.Sprintf("%s:%d", c.Config.Cache.Hostname, c.Config.Cache.Port),
Password: c.Config.Cache.Password, Password: c.Config.Cache.Password,
}) })
if _, err := cacheClient.Ping(context.Background()).Result(); err != nil { if _, err := cacheClient.Ping(context.Background()).Result(); err != nil {
c.Web.Logger.Fatalf("failed to connect to cache server: %v", err) panic(fmt.Sprintf("failed to connect to cache server: %v", err))
} }
cacheStore := store.NewRedis(cacheClient, nil) cacheStore := store.NewRedis(cacheClient, nil)
c.Cache = cache.New(cacheStore) c.Cache = cache.New(cacheStore)
@ -62,15 +71,38 @@ func (c *Container) initCache() {
func (c *Container) initDatabase() { func (c *Container) initDatabase() {
var err error var err error
addr := fmt.Sprintf("postgresql://%s:%s@%s/%s", getAddr := func(dbName string) string {
return fmt.Sprintf("postgresql://%s:%s@%s/%s",
c.Config.Database.User, c.Config.Database.User,
c.Config.Database.Password, c.Config.Database.Password,
c.Config.Database.Hostname, c.Config.Database.Hostname,
c.Config.Database.Database, dbName,
) )
c.Database, err = sql.Open("pgx", addr) }
c.Database, err = sql.Open("pgx", getAddr(c.Config.Database.Database))
if err != nil { if err != nil {
c.Web.Logger.Fatalf("failed to connect to database: %v", err) panic(fmt.Sprintf("failed to connect to database: %v", err))
}
// Check if this is a test environment
if c.Config.App.Environment == config.EnvTest {
// Drop the test database, ignoring errors in case it doesn't yet exist
_, _ = c.Database.Exec("DROP DATABASE " + c.Config.Database.TestDatabase)
// Create the test database
if _, err = c.Database.Exec("CREATE DATABASE " + c.Config.Database.TestDatabase); err != nil {
panic(fmt.Sprintf("failed to create test database: %v", err))
}
// Connect to the test database
if err = c.Database.Close(); err != nil {
panic(fmt.Sprintf("failed to close database connection: %v", err))
}
c.Database, err = sql.Open("pgx", getAddr(c.Config.Database.TestDatabase))
if err != nil {
panic(fmt.Sprintf("failed to connect to database: %v", err))
}
} }
} }
@ -78,6 +110,6 @@ func (c *Container) initORM() {
drv := entsql.OpenDB(dialect.Postgres, c.Database) drv := entsql.OpenDB(dialect.Postgres, c.Database)
c.ORM = ent.NewClient(ent.Driver(drv)) c.ORM = ent.NewClient(ent.Driver(drv))
if err := c.ORM.Schema.Create(context.Background()); err != nil { if err := c.ORM.Schema.Create(context.Background()); err != nil {
c.Web.Logger.Fatalf("failed to create database schema: %v", err) panic(fmt.Sprintf("failed to create database schema: %v", err))
} }
} }

View file

@ -7,12 +7,12 @@ import (
"os" "os"
"testing" "testing"
"goweb/config"
"goweb/container" "goweb/container"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/labstack/gommon/log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -22,10 +22,14 @@ var (
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
// Set the environment to test
if err := os.Setenv("APP_ENV", string(config.EnvTest)); err != nil {
panic(err)
}
// Start a test HTTP server // Start a test HTTP server
c = container.NewContainer() c = container.NewContainer()
BuildRouter(c) BuildRouter(c)
c.Web.Logger.SetLevel(log.DEBUG)
srv = httptest.NewServer(c.Web) srv = httptest.NewServer(c.Web)
exitVal := m.Run() exitVal := m.Run()

11
main.go
View file

@ -8,24 +8,13 @@ import (
"os/signal" "os/signal"
"time" "time"
"goweb/config"
"goweb/container" "goweb/container"
"goweb/controllers" "goweb/controllers"
"github.com/labstack/gommon/log"
) )
func main() { func main() {
c := container.NewContainer() c := container.NewContainer()
// Configure logging
switch c.Config.App.Environment {
case config.EnvProduction:
c.Web.Logger.SetLevel(log.WARN)
default:
c.Web.Logger.SetLevel(log.DEBUG)
}
// Build the router // Build the router
controllers.BuildRouter(c) controllers.BuildRouter(c)