diff --git a/envconfig.go b/envconfig.go index edc6319..9715bc8 100644 --- a/envconfig.go +++ b/envconfig.go @@ -285,6 +285,24 @@ func Process(ctx context.Context, i any, mus ...Mutator) error { }) } +// MustProcess is a helper that calls [Process] and panics if an error is +// encountered. Unlike [Process], the input value is returned, making it ideal +// for anonymous initializations: +// +// var env = envconfig.MustProcess(context.Background(), &struct{ +// Field string `env:"FIELD,required"` +// }) +// +// This is not recommend for production services, but it can be useful for quick +// CLIs and scripts that want to take advantage of envconfig's environment +// parsing at the expense of testability and graceful error handling. +func MustProcess[T any](ctx context.Context, i T, mus ...Mutator) T { + if err := Process(ctx, i, mus...); err != nil { + panic(err) + } + return i +} + // ProcessWith executes the decoding process using the provided [Config]. func ProcessWith(ctx context.Context, c *Config) error { if c == nil { diff --git a/envconfig_test.go b/envconfig_test.go index 2116aaa..5e8120a 100644 --- a/envconfig_test.go +++ b/envconfig_test.go @@ -2958,6 +2958,71 @@ func TestProcessWith(t *testing.T) { } } +func TestMustProcess(t *testing.T) { + cases := []struct { + name string + target any + exp any + env map[string]string + expPanic bool + }{ + { + name: "panics_on_error", + target: &struct { + Field string `env:"FIELD,required"` + }{}, + exp: &struct { + Field string `env:"FIELD,required"` + }{}, + env: nil, + expPanic: true, + }, + { + name: "returns_value", + target: &struct { + Field string `env:"FIELD,required"` + }{}, + exp: &struct { + Field string `env:"FIELD,required"` + }{ + Field: "value", + }, + env: map[string]string{ + "FIELD": "value", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + for k, v := range tc.env { + t.Setenv(k, v) + } + + defer func() { + if r := recover(); r != nil { + if !tc.expPanic { + t.Fatal(r) + } + } else if tc.expPanic { + t.Errorf("expected a panic") + } + }() + + ctx := context.Background() + got := MustProcess(ctx, tc.target) + + if got != tc.target { + t.Errorf("expected result to be the same object as target (%#v, %#v)", got, tc.target) + } + + if diff := cmp.Diff(tc.exp, tc.target); diff != "" { + t.Fatalf("mismatch (-want, +got):\n%s", diff) + } + }) + } +} + func TestValidateEnvName(t *testing.T) { t.Parallel()