jeudi 13 août 2020

Pattern for loading and testing environment variables

I am looking for a pattern that will allow for environment variables to be mandatory and loaded during my application init. Specifically, I'm looking for a good way to make this testable and with as little coupling as possible.

I came up with this, but there is a lot of hardcoded value names in the tests, and any new environment variable would also require an update to the tests. As I write this, I wonder if there should be an interface between my core code and the implementations that get the variables from the environment.

Code included in my main.go and used by my application init:

type Config struct {
    VAR1 string
    VAR2 string
}
// RequiredVars sets required environment variables
func (cfg *Config) RequiredVars() error {
    if cfg.VAR1 == "" {
        val1 := os.Getenv("VAR1")
        if len(val1) == 0 {
            return err.New("VAR1 not found")
        }
        cfg.VAR1 = val1
    }

    if cfg.VAR2 == "" {
        val2 := os.Getenv("VAR2")
        if len(val2) == 0 {
            return err.New("VAR2 not found")
        }
        cfg.VAR2 = val2
    }

    return nil
}

Test Success cases:

func TestGetEnvSucceeds(t *testing.T) {
    v1 := "val1"
    v2 := "val2"
    env := Config{
        VAR1: v1,
        VAR2: v2,
    }

    err := env.RequiredVars()

    assert.NoError(t, err)
}

Test Fail cases:

func TestGetEnvFails(t *testing.T) {
    var tests = []struct {
        Var1    string
        Var2    string
    }{
        {"", ""},
        {"test", ""},
        {"", "test"},
    }
    for _, tt := range tests {
        t.Run("fail", func(t *testing.T) {
            os.Setenv("VAR1", tt.Var1)
            os.Setenv("VAR2", tt.Var2)
            
            env := Config{}
            err := env.RequiredVars()
        
            assert.Error(t, err)
        })
    }
}

Aucun commentaire:

Enregistrer un commentaire