package di import ( "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/dig" ) func TestHub_New(t *testing.T) { t.Run("basic di", func(t *testing.T) { hub, err := New(module1, ValidateHub(true)) require.NoError(t, err) require.NotNil(t, hub) err = hub.Invoke(func(c C) { assert.Equal(t, c.Number, int64(100)) }) require.NoError(t, err) err = hub.Invoke(func(d D) { assert.Equal(t, d.C.Number, int64(100)) }) require.NoError(t, err) err = hub.Invoke(func(f1 F1) { assert.Equal(t, f1.Name, "f1") }) require.NoError(t, err) }) t.Run("annotation", func(t *testing.T) { k0 := &K0{} hub, err := New(module2, Annotation(func(ann *Annotated) { ann.Target = func() *K0 { return k0 } ann.Close = k0.Close })) require.NoError(t, err) require.NotNil(t, hub) // invoke now err = hub.Invoke(func(k1 K1) { assert.Equal(t, k1.J.Name, "j1") }) require.NoError(t, err) err = hub.Invoke(func(k2 K2) { assert.Equal(t, k2.J.Name, "j2") }) require.NoError(t, err) // cleanup and check it hub.Cleanup() require.True(t, k0.Closed) }) t.Run("missing deps", func(t *testing.T) { hub, err := New(moduleFailed, ValidateHub(false)) require.NoError(t, err) // won't check missing H in G, only check it after invoke require.NotNil(t, hub) err = hub.Invoke(func(g G) {}) assert.Error(t, err) assert.True(t, strings.Contains(err.Error(), "missing dependencies")) }) } var module1 = Options( Provide(func() A { return A{Name: "a"} }), Provide(func(a A) B { return B{ A: a, Age: 20, } }), Provide(func(a A, b B) C { return C{ A: a, B: b, Number: 100, } }), Provide(NewE), ) var module2 = Options( Provide(Annotated{ Name: "j1", Target: func() J { return J{Name: "j1"} }, }), Provide(Annotated{ Name: "j2", Target: func() J { return J{Name: "j2"} }, }), ) var moduleFailed = Options( Provide(func(g G) H { return H{ G: g, Name: "h", } }), ) type A struct { Name string } type B struct { A A Age int } type C struct { A A B B Number int64 } type D struct { dig.In A A B B C C } func NewE() E { return E{ F1: F1{ Name: "f1", }, F2: F2{ Name: "f2", }, } } type E struct { dig.Out F1 F1 F2 F2 } type F1 struct { Name string } type F2 struct { Name string } type G struct { Name string } type H struct { G G Name string } type J struct { Name string } type K0 struct { Closed bool } func (k *K0) Close() { k.Closed = true } type K1 struct { dig.In J J `name:"j1"` } type K2 struct { dig.In J J `name:"j2"` }