I want to run a unit test fxn in Go which has to do with env vars.
At some point I go (no pun intended)
for test := range tests {
for k, v := range test.envVars {
os.Setenv(k, v)
}
Is there a way to make sure that during the test execution, the variables set by the call to os.Setenv() above will be the only env vars available to the test function?
You can use os.Environ to obtain the current environment and os.Unsetenv to unset it.
Presumably you would also need to restore those variables after the test completes, for which you could use a subtest per environment with (*testing.T).Cleanup (https://play.golang.org/p/A5HGZwWm-NS):
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// NOTE: do NOT call t.Parallel in this subtest or its parent,
// or the environment WILL be corrupted.
//
// (However, *subtests of* t may be run in parallel.)
prevEnv := os.Environ()
for _, entry := range prevEnv {
parts := strings.SplitN(entry, "=", 2)
os.Unsetenv(parts[0])
}
for k, v := range tc.envVars {
os.Setenv(k, v)
}
t.Cleanup(func() {
for k := range tc.envVars {
os.Unsetenv(k)
}
for _, entry := range prevEnv {
parts := strings.SplitN(entry, "=", 2)
os.Setenv(parts[0], parts[1])
}
})
…
})
}
Also note that Go 1.17 adds the (*testing.T).Setenv method, which cleans up the modification automatically. However, there is not yet a corresponding (*testing.T).Unsetenv.
If you want to be able to run tests in parallel, you could instead use subtests with os/exec and the -test.run flag to re-exec the particular subtest as a subprocess of the main test process, with its own distinct environment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With