Problem
I am building a REST API in Go. The godotenv package is used to load the environment variables. Running go run main.go, the project runs the API as expected, the environment variables are loaded.
However, when wanting to run the test using: go test ./... - which runs config/config_test.go among others - it throws the following error: Error loading .env file (as specified in function).
Given the following project structure:
> app
> auth
> config
- config.go
- config_test.go
> migrations
> static
> vendor
- .env
- .gitignore
- docker-compose.yml
- go.mod
- go.sum
- main.go
- README.md
In config.go, I use the following function to load the Database configuration.
func GetConfig() *Config {
err := godotenv.Load(".env")
if err != nil {
log.Fatalf("Error loading .env file")
}
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_DATABASE")
dbUsername := os.Getenv("DB_USERNAME")
dbPassword := os.Getenv("DB_PASSWORD")
return &Config{
DB: &DBConfig{
Connection: "mysql",
Host: dbHost,
Port: dbPort,
Username: dbUsername,
Password: dbPassword,
Name: dbName,
Charset: "utf8",
},
}
}
I understand that it works when running from root, because the .env resides in root. When running config/config_test.go, it tries to look for the .env file in the /config/.env. If I change the line: err := godotenv.Load(".env") to err := godotenv.Load("../.env"), the config_test.go runs successfully, but the go run main.go from root does not run successfully.
Question
How can I load the .env location dynamically from the GetConfig() function in config.go, so that both the go test ./... and go run main.go can load the .env?
Edit
I am aware that passing a path string parameter to the GetConfig() function would work in my application (I am initializing this config in the app package). However, I want to create multiple tests in different directories, and prefer not to pass a parameter. Is there another way to accomplish this?
GetConfig. Then inmain.gopass.env, and in your test, pass./testdata/.envor whatever. - Flimzynot wanting to relytoprefer not to, because I believe there should be another solution and will try one of the suggested solutions provided by @Inian. - Eric Landheer