Skip to content

Commit bbaf784

Browse files
sethvargoimjasonh
andauthored
Add MustProcess which panics on errors (#115)
* MustProcess: panic if processing fails, return the value Signed-off-by: Jason Hall <[email protected]> * Add MustProcess that panics if processing fails --------- Signed-off-by: Jason Hall <[email protected]> Co-authored-by: Jason Hall <[email protected]>
1 parent e51a54f commit bbaf784

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

envconfig.go

+18
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,24 @@ func Process(ctx context.Context, i any, mus ...Mutator) error {
285285
})
286286
}
287287

288+
// MustProcess is a helper that calls [Process] and panics if an error is
289+
// encountered. Unlike [Process], the input value is returned, making it ideal
290+
// for anonymous initializations:
291+
//
292+
// var env = envconfig.MustProcess(context.Background(), &struct{
293+
// Field string `env:"FIELD,required"`
294+
// })
295+
//
296+
// This is not recommend for production services, but it can be useful for quick
297+
// CLIs and scripts that want to take advantage of envconfig's environment
298+
// parsing at the expense of testability and graceful error handling.
299+
func MustProcess[T any](ctx context.Context, i T, mus ...Mutator) T {
300+
if err := Process(ctx, i, mus...); err != nil {
301+
panic(err)
302+
}
303+
return i
304+
}
305+
288306
// ProcessWith executes the decoding process using the provided [Config].
289307
func ProcessWith(ctx context.Context, c *Config) error {
290308
if c == nil {

envconfig_test.go

+65
Original file line numberDiff line numberDiff line change
@@ -2958,6 +2958,71 @@ func TestProcessWith(t *testing.T) {
29582958
}
29592959
}
29602960

2961+
func TestMustProcess(t *testing.T) {
2962+
cases := []struct {
2963+
name string
2964+
target any
2965+
exp any
2966+
env map[string]string
2967+
expPanic bool
2968+
}{
2969+
{
2970+
name: "panics_on_error",
2971+
target: &struct {
2972+
Field string `env:"FIELD,required"`
2973+
}{},
2974+
exp: &struct {
2975+
Field string `env:"FIELD,required"`
2976+
}{},
2977+
env: nil,
2978+
expPanic: true,
2979+
},
2980+
{
2981+
name: "returns_value",
2982+
target: &struct {
2983+
Field string `env:"FIELD,required"`
2984+
}{},
2985+
exp: &struct {
2986+
Field string `env:"FIELD,required"`
2987+
}{
2988+
Field: "value",
2989+
},
2990+
env: map[string]string{
2991+
"FIELD": "value",
2992+
},
2993+
},
2994+
}
2995+
2996+
for _, tc := range cases {
2997+
t.Run(tc.name, func(t *testing.T) {
2998+
for k, v := range tc.env {
2999+
t.Setenv(k, v)
3000+
}
3001+
3002+
defer func() {
3003+
if r := recover(); r != nil {
3004+
if !tc.expPanic {
3005+
t.Fatal(r)
3006+
}
3007+
} else if tc.expPanic {
3008+
t.Errorf("expected a panic")
3009+
}
3010+
}()
3011+
3012+
ctx := context.Background()
3013+
got := MustProcess(ctx, tc.target)
3014+
3015+
if got != tc.target {
3016+
t.Errorf("expected result to be the same object as target (%#v, %#v)", got, tc.target)
3017+
}
3018+
3019+
if diff := cmp.Diff(tc.exp, tc.target); diff != "" {
3020+
t.Fatalf("mismatch (-want, +got):\n%s", diff)
3021+
}
3022+
})
3023+
}
3024+
}
3025+
29613026
func TestValidateEnvName(t *testing.T) {
29623027
t.Parallel()
29633028

0 commit comments

Comments
 (0)