diff --git a/configurator.go b/configurator.go index 936181d..8a074b7 100644 --- a/configurator.go +++ b/configurator.go @@ -23,7 +23,7 @@ type Configurator interface { func GetEnvString(config Configurator, field string) string { defer func() { if r := recover(); r != nil { - log.Panicf("configurator has no field named '%s'", field) + log.Panicf("configurator has no string field named '%s'", field) } }() value, exists := os.LookupEnv(field) @@ -38,6 +38,9 @@ func GetEnvString(config Configurator, field string) string { func GetEnvBool(config Configurator, field string) bool { defer func() { if r := recover(); r != nil { + if reflect.ValueOf(config).FieldByName(field).IsValid() { + log.Panicf("configurator field '%s' is not a bool", field) + } log.Panicf("configurator has no field named '%s'", field) } }() @@ -53,6 +56,9 @@ func GetEnvBool(config Configurator, field string) bool { func GetEnvInt(config Configurator, field string) int { defer func() { if r := recover(); r != nil { + if reflect.ValueOf(config).FieldByName(field).IsValid() { + log.Panicf("configurator field '%s' is not an int", field) + } log.Panicf("configurator has no field named '%s'", field) } }() @@ -68,6 +74,9 @@ func GetEnvInt(config Configurator, field string) int { func GetEnvFloat(config Configurator, field string) float64 { defer func() { if r := recover(); r != nil { + if reflect.ValueOf(config).FieldByName(field).IsValid() { + log.Panicf("configurator field '%s' is not a float", field) + } log.Panicf("configurator has no field named '%s'", field) } }() diff --git a/configurator_test.go b/configurator_test.go index 1334976..52d50f0 100644 --- a/configurator_test.go +++ b/configurator_test.go @@ -244,6 +244,47 @@ func TestPanicMessageIncludesFieldName(t *testing.T) { panicCheck(func() { config_iface.GetEnvBool("DOES_NOT_EXIST") }) } +func TestPanicOnExistingFieldWrongType(t *testing.T) { + var field_name, field_type string + panicCheck := func(f func()) { + defer func() { + r := recover() + if r == nil { + t.Errorf("Reading field using wrong type did not cause panic") + } else { + switch v := r.(type) { + case string: + if !strings.Contains(v, field_name) { + t.Errorf("Panic msg should contain field name '%s'. Got '%v'", field_name, r) + } + if !strings.Contains(v, field_type) { + t.Errorf("Panic msg should contain field type. Got '%v'", r) + } + case error: + if !strings.Contains(v.Error(), "DOES_NOT_EXIST") { + t.Errorf("Panic msg should contain field name '%s'. Got '%v'", field_name, r) + } + if !strings.Contains(v.Error(), field_type) { + t.Errorf("Panic msg should contain field type. Got '%v'", r) + } + default: + t.Errorf("Panic's type is unkown. Cannot check error msg. Type is '%T'", r) + } + } + }() + f() + } + field_name = "DB_HOST" + field_type = "int" + panicCheck(func() { config_iface.GetEnvInt("DB_HOST") }) + field_type = "float" + panicCheck(func() { config_iface.GetEnvFloat("DB_HOST") }) + field_type = "bool" + panicCheck(func() { config_iface.GetEnvBool("DB_HOST") }) + field_name = "DB_PORT" + field_type = "string" + panicCheck(func() { config_iface.GetEnvString("DB_PORT") }) +} func use(vals ...any) { for _, val := range vals { _ = val