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.go
pass.env
, and in your test, pass./testdata/.env
or whatever. – Apocopatenot wanting to rely
toprefer not to
, because I believe there should be another solution and will try one of the suggested solutions provided by @Inian. – Unimpeachable