package config_test import ( "os" "reflect" "strings" "testing" "github.com/knadh/koanf" "github.com/knadh/koanf/parsers/yaml" "github.com/knadh/koanf/providers/env" "github.com/knadh/koanf/providers/file" "github.com/knadh/koanf/providers/structs" ) type structConfig struct { Debug bool `koanf:"debug"` MultiWordVar string `koanf:"multi_word_var"` DB db `koanf:"db"` } type db struct { Host string `koanf:"host"` Username string `koanf:"username"` Password string `koanf:"password"` MultiWordNestedVar string `koanf:"multi_word_nested_var"` NestedMultiWordConfig nestedMultiWordConfig `koanf:"nested_multi_word_config"` } type nestedMultiWordConfig struct { DownHere string `koanf:"down_here"` } const ( prefix = "EB_" delimiter = "." separator = "__" ) func callbackEnv(source string) string { base := strings.ToLower(strings.TrimPrefix(source, prefix)) return strings.ReplaceAll(base, separator, delimiter) } func TestLoadingDefaultConfigFromStruct(t *testing.T) { k := koanf.New(".") testStruct := structConfig{ Debug: false, MultiWordVar: "Im complex in default", DB: db{ Host: "localhost", Username: "hossein", Password: "1234", MultiWordNestedVar: "Oh this is too long", }, } if err := k.Load(structs.Provider(testStruct, "koanf"), nil); err != nil { t.Fatalf("error loading default config: %s", err) } var instance structConfig if err := k.Unmarshal("", &instance); err != nil { t.Fatalf("error unmarshaling config: %s", err) } if !reflect.DeepEqual(instance, testStruct) { t.Fatalf("expected: %+v, got: %+v", testStruct, instance) } } func TestLoadingConfigFromYamlFile(t *testing.T) { k := koanf.New(".") ymlConfigTest := []byte(`debug: false multi_word_var: "I'm complex in config.yml" db: host: "localhost" username: "ali" password: "passwd" multi_word_nested_var: "WHAT??"`) ymlFile, _ := os.Create("test.yml") defer ymlFile.Close() defer os.Remove("test.yml") ymlFile.Write(ymlConfigTest) // load configuration from yaml file if err := k.Load(file.Provider("test.yml"), yaml.Parser()); err != nil { t.Logf("error loading config from `config.yml` file: %s", err) } want := structConfig{ Debug: false, MultiWordVar: "I'm complex in config.yml", DB: db{ Host: "localhost", Username: "ali", Password: "passwd", MultiWordNestedVar: "WHAT??", }, } var instance structConfig if err := k.Unmarshal("", &instance); err != nil { t.Fatalf("error unmarshaling config: %s", err) } if !reflect.DeepEqual(want, instance) { t.Fatalf("expected: %+v, got: %+v", want, instance) } } func TestLoadConfigFromEnvironmentVariable(t *testing.T) { k := koanf.New(".") os.Setenv("EB_DEBUG", "false") os.Setenv("EB_MULTI_WORD_VAR", "this is multi word var") os.Setenv("EB_DB__HOST", "localhost") os.Setenv("EB_DB__USERNAME", "hossein") os.Setenv("EB_DB__PASSWORD", "1234") os.Setenv("EB_DB__MULTI_WORD_NESTED_VAR", "testing make it easy (:") os.Setenv("EB_DB__NESTED_MULTI_WORD_CONFIG__DOWN_HERE", "im here") if err := k.Load(env.Provider(prefix, delimiter, callbackEnv), nil); err != nil { t.Logf("error loading environment variables: %s", err) } var instance structConfig if err := k.Unmarshal("", &instance); err != nil { t.Fatalf("error unmarshaling config: %s", err) } want := structConfig{ Debug: false, MultiWordVar: "this is multi word var", DB: db{ Host: "localhost", Username: "hossein", Password: "1234", MultiWordNestedVar: "testing make it easy (:", NestedMultiWordConfig: nestedMultiWordConfig{DownHere: "im here"}, }, } if !reflect.DeepEqual(instance, want) { t.Fatalf("expected: %+v, got: %+v", want, instance) } }