There are two ways to test code that uses environment variables in Go:
Let’s take a look at both implementations:
Set environment variable in test scope
Since Go version 1.15 you can set a environment variable only in the scope of a test. You can set the variable like this:
// main.go func main() { fmt.Println(funcUsingEnvVar()) } func funcUsingEnvVar() string { return os.Getenv("APP_ENV") }
// main_test.go func TestSettingEnvVar(t *testing.T) { t.Setenv("APP_ENV", "dev") if funcUsingEnvVar() != "dev" { t.Fatal("APP_ENV not dev") } }
The issue with this approach is that it sets the environment variable for the duration of the test. If other tests are running in parallel they will also have this variable set.
Use a function reference to test the environment variable
This approach is more isolated and allows tests to run in parallel with different variables.
Instead of calling os.Getenv directly in the function we’re using a function reference:
package main func main() { fmt.Println(funcUsingEnvVar(os.Getenv)) } func funcUsingEnvVar(getEnv func(string) string) string { return getEnv("APP_ENV") }
In the test, we can then replace the reference with another function:
func TestMockingEnvVar(t *testing.T) { calledWith := "" mockGetEnv := func(s string) string { calledWith = s return "dev" } appEnv := funcUsingEnvVar(mockGetEnv) if calledWith != "APP_ENV" { t.Fatalf("did not call getEnv with APP_ENV") } if appEnv != "dev" { t.Fatalf("return value not dev") } }
Conclusion
This post helps you to test Go code that uses environment variables.
Follow me on LinkedIn for more Go content.