Skip to content

Commit

Permalink
Add documentation and tests for soft group values
Browse files Browse the repository at this point in the history
This adds documentation regarding soft group values feature and also
adds test cases to check this feature works with modules, `Supply`,
`Decorate` and `Annotate`.
  • Loading branch information
EstebanOlmedo authored and sywhang committed Aug 4, 2022
1 parent ff16dae commit 818c88f
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 14 deletions.
79 changes: 65 additions & 14 deletions inout.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,25 +163,76 @@ import "go.uber.org/dig"
// Note that values in a value group are unordered. Fx makes no guarantees
// about the order in which these values will be produced.
//
// To declare a soft relationship between a group an its constructors, use the
// `soft` option on the group tag (`group:"[groupname],soft"`). A soft group
// will be populated only with values from already-executed constructors, this
// means constructors of soft value groups will be called only if they provide
// another requested value.
// To declare a soft relationship between a group and its constructors, use
// the `soft` option on the group tag (`group:"[groupname],soft"`), this
// option can only be used for input parameters, e.g. `fx.In` structures.
// A soft group will be populated only with values from already-executed
// constructors.
//
// type Params struct {
// fx.In
// fx.In
//
// Handlers []Handler `group:"server"`
// Logger *zap.Logger
// Handlers []Handler `group:"server"`
// Logger *zap.Logger
// }
// func NewHandlerAndLogger() (Handler, *zap.Logger) { ... }
// func NewHandler() Handler { ... }
// func Foo(Params) { ... }
//
// When `NewHandlerAndLogger` and `NewHandler`are provided, and `Foo` invoked,
// the only constructor called is `NewHandler`, because this also provides
// `*zap.Logger` needed in the `Params` struct.
// NewHandlerAndLogger := func() (Handler, *zap.Logger) { ... }
// NewHandler := func() Handler { ... }
// Foo := func(Params) { ... }
//
// app := fx.New(
// fx.Provide(NewHandlerAndLogger),
// fx.Provide(NewHandler),
// fx.Invoke(Foo),
// )
//
// The only constructor called is `NewHandler`, because this also provides
// `*zap.Logger` needed in the `Params` struct received by `foo`
//
// In the next example, the slice `s` isn't populated as the provider would be
// called only because of `strings` soft group value
//
// app := fx.New(
// fx.Provide(
// fx.Annotate(
// func() (string,int) { return "hello" },
// fx.ResultTags(`group:"strings"`),
// ),
// ),
// fx.Invoke(
// fx.Annotate(func(s []string) {
// // s will be an empty slice
// },
// fx.ParamTags(`group:"strings,soft"`),
// ),
// ),
// )
//
// In the next example, the slice `s` will be populated because there is a
// consumer for the same type which hasn't a `soft` dependency
//
// app := fx.New(
// fx.Provide(
// fx.Annotate(
// func() string { "hello" },
// fx.ResultTags(`group:"strings"`),
// ),
// ),
// fx.Invoke(
// fx.Annotate(func(b []string) {
// // b will be ["hello"]
// },
// fx.ParamTags(`group:"strings"`),
// ),
// ),
// fx.Invoke(
// fx.Annotate(func(s []string) {
// // s will be ["hello"]
// },
// fx.ParamTags(`group:"strings,soft"`),
// ),
// ),
// )
//
// # Unexported fields
//
Expand Down
15 changes: 15 additions & 0 deletions module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ func TestModuleSuccess(t *testing.T) {
defer app.RequireStart().RequireStop()
require.NoError(t, app.Err())
})
t.Run("soft provided to fx.Out struct", func(t *testing.T) {
t.Parallel()

type Result struct {
fx.Out

Bars []int `group:"bar,soft"`
}
app := NewForTest(t,
fx.Provide(func() Result { return Result{Bars: []int{1, 2, 3}} }),
)
err := app.Err()
require.Error(t, err, "failed to create app")
assert.Contains(t, err.Error(), "cannot use soft with result value groups")
})
t.Run("invoke from nested module", func(t *testing.T) {
t.Parallel()
invokeRan := false
Expand Down

0 comments on commit 818c88f

Please sign in to comment.