diff --git a/di_example_test.go b/di_example_test.go deleted file mode 100644 index e450299..0000000 --- a/di_example_test.go +++ /dev/null @@ -1,211 +0,0 @@ -package do - -import ( - "fmt" -) - -func ExampleProvide() { - injector := New() - - type test struct { - foobar string - } - - Provide(injector, func(i *Injector) (*test, error) { - return &test{foobar: "foobar"}, nil - }) - value, err := Invoke[*test](injector) - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar} - // -} - -func ExampleInvoke() { - injector := New() - - type test struct { - foobar string - } - - Provide(injector, func(i *Injector) (*test, error) { - return &test{foobar: "foobar"}, nil - }) - value, err := Invoke[*test](injector) - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar} - // -} - -func ExampleMustInvoke() { - injector := New() - - type test struct { - foobar string - } - - Provide(injector, func(i *Injector) (*test, error) { - return &test{foobar: "foobar"}, nil - }) - value := MustInvoke[*test](injector) - - fmt.Println(value) - // Output: - // &{foobar} -} - -func ExampleProvideNamed() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamed(injector, "my_service", func(i *Injector) (*test, error) { - return &test{foobar: "foobar"}, nil - }) - value, err := InvokeNamed[*test](injector, "my_service") - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar} - // -} - -func ExampleInvokeNamed() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamed(injector, "my_service", func(i *Injector) (*test, error) { - return &test{foobar: "foobar"}, nil - }) - value, err := InvokeNamed[*test](injector, "my_service") - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar} - // -} - -func ExampleMustInvokeNamed() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamed(injector, "my_service", func(i *Injector) (*test, error) { - return &test{foobar: "foobar"}, nil - }) - value := MustInvokeNamed[*test](injector, "my_service") - - fmt.Println(value) - // Output: - // &{foobar} -} - -func ExampleProvideValue() { - injector := New() - - type test struct { - foobar string - } - - ProvideValue(injector, &test{foobar: "foobar"}) - value, err := Invoke[*test](injector) - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar} - // -} - -func ExampleProvideNamedValue() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamedValue(injector, "my_service", &test{foobar: "foobar"}) - value, err := InvokeNamed[*test](injector, "my_service") - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar} - // -} - -func ExampleOverride() { - injector := New() - - type test struct { - foobar string - } - - Provide(injector, func(i *Injector) (*test, error) { - return &test{foobar: "foobar1"}, nil - }) - Override(injector, func(i *Injector) (*test, error) { - return &test{foobar: "foobar2"}, nil - }) - value, err := Invoke[*test](injector) - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar2} - // -} - -func ExampleOverrideNamed() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamed(injector, "my_service", func(i *Injector) (*test, error) { - return &test{foobar: "foobar1"}, nil - }) - OverrideNamed(injector, "my_service", func(i *Injector) (*test, error) { - return &test{foobar: "foobar2"}, nil - }) - value, err := InvokeNamed[*test](injector, "my_service") - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar2} - // -} - -func ExampleOverrideNamedValue() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamedValue(injector, "my_service", &test{foobar: "foobar1"}) - OverrideNamedValue(injector, "my_service", &test{foobar: "foobar2"}) - value, err := InvokeNamed[*test](injector, "my_service") - - fmt.Println(value) - fmt.Println(err) - // Output: - // &{foobar2} - // -} diff --git a/di_test.go b/di_test.go deleted file mode 100644 index a41be9e..0000000 --- a/di_test.go +++ /dev/null @@ -1,403 +0,0 @@ -package do - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestDefaultInjector(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - - DefaultInjector = New() - - Provide(nil, func(i *Injector) (*test, error) { - return &test{foobar: "42"}, nil - }) - - is.Len(DefaultInjector.services, 1) - - service, err := Invoke[*test](nil) - - is.Equal(test{foobar: "42"}, *service) - is.Nil(err) -} - -func TestProvide(t *testing.T) { - is := assert.New(t) - - type test struct{} - - i := New() - - Provide(i, func(i *Injector) (*test, error) { - return &test{}, nil - }) - - Provide(i, func(i *Injector) (test, error) { - return test{}, fmt.Errorf("error") - }) - - is.Panics(func() { - // try to erase previous instance - Provide(i, func(i *Injector) (test, error) { - return test{}, fmt.Errorf("error") - }) - }) - - is.Len(i.services, 2) - - s1, ok1 := i.services["*do.test"] - is.True(ok1) - if ok1 { - s, ok := s1.(Service[*test]) - is.True(ok) - if ok { - is.Equal("*do.test", s.getName()) - } - } - - s2, ok2 := i.services["do.test"] - is.True(ok2) - if ok2 { - s, ok := s2.(Service[test]) - is.True(ok) - if ok { - is.Equal("do.test", s.getName()) - } - } - - _, ok3 := i.services["*do.plop"] - is.False(ok3) -} - -func TestProvideValue(t *testing.T) { - is := assert.New(t) - - i := New() - - type test struct { - foobar string - } - _test := test{foobar: "foobar"} - - ProvideNamedValue(i, "foobar", 42) - ProvideNamedValue(i, "hello", _test) - - is.Len(i.services, 2) - - s1, ok1 := i.services["foobar"] - is.True(ok1) - if ok1 { - s, ok := s1.(Service[int]) - is.True(ok) - if ok { - is.Equal("foobar", s.getName()) - instance, err := s.getInstance(i) - is.EqualValues(42, instance) - is.Nil(err) - } - } - - s2, ok2 := i.services["hello"] - is.True(ok2) - if ok2 { - s, ok := s2.(Service[test]) - is.True(ok) - if ok { - is.Equal("hello", s.getName()) - instance, err := s.getInstance(i) - is.EqualValues(_test, instance) - is.Nil(err) - } - } -} - -func TestInvoke(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - - i := New() - - Provide(i, func(i *Injector) (test, error) { - return test{foobar: "foobar"}, nil - }) - - is.Len(i.services, 1) - - s0a, ok0a := i.services["do.test"] - is.True(ok0a) - - s0b, ok0b := s0a.(*ServiceLazy[test]) - is.True(ok0b) - is.False(s0b.built) - - s1, err1 := Invoke[test](i) - is.Nil(err1) - if err1 == nil { - is.Equal("foobar", s1.foobar) - } - - is.True(s0b.built) - - _, err2 := Invoke[*test](i) - is.NotNil(err2) - is.Errorf(err2, "do: service not found") -} - -func TestInvokeNamed(t *testing.T) { - is := assert.New(t) - - i := New() - - type test struct { - foobar string - } - _test := test{foobar: "foobar"} - - ProvideNamedValue(i, "foobar", 42) - ProvideNamedValue(i, "hello", _test) - - is.Len(i.services, 2) - - service0, err0 := InvokeNamed[string](i, "plop") - is.NotNil(err0) - is.Empty(service0) - - instance1, err1 := InvokeNamed[test](i, "hello") - is.Nil(err1) - is.EqualValues(_test, instance1) - is.EqualValues("foobar", instance1.foobar) - - instance2, err2 := InvokeNamed[int](i, "foobar") - is.Nil(err2) - is.EqualValues(42, instance2) -} - -func TestMustInvoke(t *testing.T) { - is := assert.New(t) - - i := New() - - type test struct { - foobar string - } - _test := test{foobar: "foobar"} - - Provide(i, func(i *Injector) (test, error) { - return _test, nil - }) - - is.Len(i.services, 1) - - is.Panics(func() { - _ = MustInvoke[string](i) - }) - - is.NotPanics(func() { - instance1 := MustInvoke[test](i) - is.EqualValues(_test, instance1) - }) -} - -func TestMustInvokeNamed(t *testing.T) { - is := assert.New(t) - - i := New() - - ProvideNamedValue(i, "foobar", 42) - - is.Len(i.services, 1) - - is.Panics(func() { - _ = MustInvokeNamed[string](i, "hello") - }) - - is.Panics(func() { - _ = MustInvokeNamed[string](i, "foobar") - }) - - is.NotPanics(func() { - instance1 := MustInvokeNamed[int](i, "foobar") - is.EqualValues(42, instance1) - }) -} - -func TestShutdown(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - - i := New() - - Provide(i, func(i *Injector) (test, error) { - return test{foobar: "foobar"}, nil - }) - - instance, err := Invoke[test](i) - is.Equal(test{foobar: "foobar"}, instance) - is.Nil(err) - - err = Shutdown[test](i) - is.Nil(err) - - instance, err = Invoke[test](i) - is.Empty(instance) - is.NotNil(err) - - err = Shutdown[test](i) - is.NotNil(err) -} - -func TestMustShutdown(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - - i := New() - - Provide(i, func(i *Injector) (test, error) { - return test{foobar: "foobar"}, nil - }) - - instance, err := Invoke[test](i) - is.Equal(test{foobar: "foobar"}, instance) - is.Nil(err) - - is.NotPanics(func() { - MustShutdown[test](i) - }) - - instance, err = Invoke[test](i) - is.Empty(instance) - is.NotNil(err) - - is.Panics(func() { - MustShutdown[test](i) - }) -} - -func TestShutdownNamed(t *testing.T) { - is := assert.New(t) - - i := New() - - ProvideNamedValue(i, "foobar", 42) - - instance, err := InvokeNamed[int](i, "foobar") - is.Equal(42, instance) - is.Nil(err) - - err = ShutdownNamed(i, "foobar") - is.Nil(err) - - instance, err = InvokeNamed[int](i, "foobar") - is.Empty(instance) - is.NotNil(err) - - err = ShutdownNamed(i, "foobar") - is.NotNil(err) -} - -func TestMustShutdownNamed(t *testing.T) { - is := assert.New(t) - - i := New() - - ProvideNamedValue(i, "foobar", 42) - - instance, err := InvokeNamed[int](i, "foobar") - is.Equal(42, instance) - is.Nil(err) - - is.NotPanics(func() { - MustShutdownNamed(i, "foobar") - }) - - instance, err = InvokeNamed[int](i, "foobar") - is.Empty(instance) - is.NotNil(err) - - is.Panics(func() { - MustShutdownNamed(i, "foobar") - }) -} - -func TestDoubleInjection(t *testing.T) { - is := assert.New(t) - - type test struct{} - - i := New() - - is.NotPanics(func() { - Provide(i, func(i *Injector) (*test, error) { - return &test{}, nil - }) - }) - - is.PanicsWithError("DI: service `*do.test` has already been declared", func() { - Provide(i, func(i *Injector) (*test, error) { - return &test{}, nil - }) - }) - - is.PanicsWithError("DI: service `*do.test` has already been declared", func() { - ProvideValue(i, &test{}) - }) - - is.PanicsWithError("DI: service `*do.test` has already been declared", func() { - ProvideNamed(i, "*do.test", func(i *Injector) (*test, error) { - return &test{}, nil - }) - }) - - is.PanicsWithError("DI: service `*do.test` has already been declared", func() { - ProvideNamedValue(i, "*do.test", &test{}) - }) -} - -func TestOverride(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar int - } - - i := New() - - is.NotPanics(func() { - Provide(i, func(i *Injector) (*test, error) { - return &test{42}, nil - }) - is.Equal(42, MustInvoke[*test](i).foobar) - - Override(i, func(i *Injector) (*test, error) { - return &test{1}, nil - }) - is.Equal(1, MustInvoke[*test](i).foobar) - - OverrideNamed(i, "*do.test", func(i *Injector) (*test, error) { - return &test{2}, nil - }) - is.Equal(2, MustInvoke[*test](i).foobar) - - OverrideValue(i, &test{3}) - is.Equal(3, MustInvoke[*test](i).foobar) - - OverrideNamedValue(i, "*do.test", &test{4}) - is.Equal(4, MustInvoke[*test](i).foobar) - }) -} diff --git a/go.mod b/go.mod index 2ee7fe6..c5dc788 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,3 @@ module github.com/samber/do go 1.18 - -require github.com/stretchr/testify v1.8.1 - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/go.sum b/go.sum index 2ec90f7..e69de29 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +0,0 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/injector_example_test.go b/injector_example_test.go deleted file mode 100644 index 528cfdd..0000000 --- a/injector_example_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package do - -import ( - "database/sql" - "fmt" -) - -type dbService struct { - db *sql.DB -} - -func (s *dbService) HealthCheck() error { - return nil -} - -func (s *dbService) Shutdown() error { - return nil -} - -func dbServiceProvider(i *Injector) (*dbService, error) { - return &dbService{db: nil}, nil -} - -func ExampleNew() { - injector := New() - - ProvideNamedValue(injector, "PG_URI", "postgres://user:pass@host:5432/db") - uri, err := InvokeNamed[string](injector, "PG_URI") - - fmt.Println(uri) - fmt.Println(err) - // Output: - // postgres://user:pass@host:5432/db - // -} - -func ExampleDefaultInjector() { - ProvideNamedValue(nil, "PG_URI", "postgres://user:pass@host:5432/db") - uri, err := InvokeNamed[string](nil, "PG_URI") - - fmt.Println(uri) - fmt.Println(err) - // Output: - // postgres://user:pass@host:5432/db - // -} - -func ExampleNewWithOpts() { - injector := NewWithOpts(&InjectorOpts{ - HookAfterShutdown: func(injector *Injector, serviceName string) { - fmt.Printf("service shutdown: %s\n", serviceName) - }, - }) - - ProvideNamed(injector, "PG_URI", func(i *Injector) (string, error) { - return "postgres://user:pass@host:5432/db", nil - }) - MustInvokeNamed[string](injector, "PG_URI") - _ = injector.Shutdown() - - // Output: - // service shutdown: PG_URI -} - -func ExampleInjector_ListProvidedServices() { - injector := New() - - ProvideNamedValue(injector, "PG_URI", "postgres://user:pass@host:5432/db") - services := injector.ListProvidedServices() - - fmt.Println(services) - // Output: - // [PG_URI] -} - -func ExampleInjector_ListInvokedServices_invoked() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamed(injector, "SERVICE_NAME", func(i *Injector) (test, error) { - return test{foobar: "foobar"}, nil - }) - _, _ = InvokeNamed[test](injector, "SERVICE_NAME") - services := injector.ListInvokedServices() - - fmt.Println(services) - // Output: - // [SERVICE_NAME] -} - -func ExampleInjector_ListInvokedServices_notInvoked() { - injector := New() - - type test struct { - foobar string - } - - ProvideNamed(injector, "SERVICE_NAME", func(i *Injector) (test, error) { - return test{foobar: "foobar"}, nil - }) - services := injector.ListInvokedServices() - - fmt.Println(services) - // Output: - // [] -} - -func ExampleInjector_HealthCheck() { - injector := New() - - Provide(injector, dbServiceProvider) - health := injector.HealthCheck() - - fmt.Println(health) - // Output: - // map[*do.dbService:] -} - -func ExampleInjector_Shutdown() { - injector := New() - - Provide(injector, dbServiceProvider) - err := injector.Shutdown() - - fmt.Println(err) - // Output: - // -} - -func ExampleInjector_Clone() { - injector := New() - - ProvideNamedValue(injector, "PG_URI", "postgres://user:pass@host:5432/db") - injector2 := injector.Clone() - services := injector2.ListProvidedServices() - - fmt.Println(services) - // Output: - // [PG_URI] -} diff --git a/injector_test.go b/injector_test.go deleted file mode 100644 index c1eac84..0000000 --- a/injector_test.go +++ /dev/null @@ -1,347 +0,0 @@ -package do - -import ( - "fmt" - "reflect" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestInjectorNew(t *testing.T) { - is := assert.New(t) - - i := New() - is.NotNil(i) - is.Empty(i.services) -} - -func TestInjectorNewWithOpts(t *testing.T) { - is := assert.New(t) - - count := 0 - - i := NewWithOpts(&InjectorOpts{ - HookAfterRegistration: func(injector *Injector, serviceName string) { - is.Equal("foobar", serviceName) - count++ - }, - HookAfterShutdown: func(injector *Injector, serviceName string) { - is.Equal("foobar", serviceName) - count++ - }, - }) - - ProvideNamedValue(i, "foobar", 42) - - is.NotPanics(func() { - MustInvokeNamed[int](i, "foobar") - }) - - err := i.Shutdown() - is.Nil(err) - - is.Equal(2, count) -} - -func TestInjectorListProvidedServices(t *testing.T) { - is := assert.New(t) - - i := New() - - is.NotPanics(func() { - ProvideValue[int](i, 42) - ProvideValue[float64](i, 21) - }) - - is.NotPanics(func() { - services := i.ListProvidedServices() - is.ElementsMatch([]string{"int", "float64"}, services) - }) -} - -func TestInjectorListInvokedServices(t *testing.T) { - is := assert.New(t) - - i := New() - - is.NotPanics(func() { - ProvideValue[int](i, 42) - ProvideValue[float64](i, 21) - MustInvoke[int](i) - }) - - is.NotPanics(func() { - services := i.ListInvokedServices() - is.Equal([]string{"int"}, services) - }) -} - -type testHealthCheck struct { -} - -func (t *testHealthCheck) HealthCheck() error { - return fmt.Errorf("broken") -} - -func TestInjectorHealthCheck(t *testing.T) { - is := assert.New(t) - - i := New() - - is.NotPanics(func() { - ProvideValue[int](i, 42) - ProvideNamed(i, "testHealthCheck", func(i *Injector) (*testHealthCheck, error) { - return &testHealthCheck{}, nil - }) - }) - - // before invocation - is.NotPanics(func() { - got := i.HealthCheck() - expected := map[string]error{ - "int": nil, - "testHealthCheck": nil, - } - - is.Equal(expected, got) - }) - - is.NotPanics(func() { - MustInvokeNamed[int](i, "int") - MustInvokeNamed[*testHealthCheck](i, "testHealthCheck") - }) - - // after invocation - is.NotPanics(func() { - got := i.HealthCheck() - expected := map[string]error{ - "int": nil, - "testHealthCheck": fmt.Errorf("broken"), - } - - is.Equal(expected, got) - }) -} - -func TestInjectorExists(t *testing.T) { - is := assert.New(t) - - i := New() - - service := &ServiceEager[int]{ - name: "foobar", - instance: 42, - } - i.services["foobar"] = service - - is.True(i.exists("foobar")) - is.False(i.exists("foobaz")) -} - -func TestInjectorGet(t *testing.T) { - is := assert.New(t) - - i := New() - - service := &ServiceEager[int]{ - name: "foobar", - instance: 42, - } - i.services["foobar"] = service - - // existing service - { - s1, ok1 := i.get("foobar") - is.True(ok1) - is.NotEmpty(s1) - if ok1 { - s, ok := s1.(Service[int]) - is.True(ok) - - v, err := s.getInstance(i) - is.Nil(err) - is.Equal(42, v) - } - } - - // not existing service - { - s2, ok2 := i.get("foobaz") - is.False(ok2) - is.Empty(s2) - } -} - -func TestInjectorSet(t *testing.T) { - is := assert.New(t) - - i := New() - - service1 := &ServiceEager[int]{ - name: "foobar", - instance: 42, - } - - service2 := &ServiceEager[int]{ - name: "foobar", - instance: 21, - } - - i.set("foobar", service1) - is.Len(i.services, 1) - - s1, ok1 := i.services["foobar"] - is.True(ok1) - is.True(reflect.DeepEqual(service1, s1)) - - // erase - i.set("foobar", service2) - is.Len(i.services, 1) - - s2, ok2 := i.services["foobar"] - is.True(ok2) - is.True(reflect.DeepEqual(service2, s2)) -} - -func TestInjectorRemove(t *testing.T) { - is := assert.New(t) - - i := New() - - service := &ServiceEager[int]{ - name: "foobar", - instance: 42, - } - - i.set("foobar", service) - is.Len(i.services, 1) - i.remove("foobar") - is.Len(i.services, 0) -} - -func TestInjectorForEach(t *testing.T) { - is := assert.New(t) - - i := New() - - service := &ServiceEager[int]{ - name: "foobar", - instance: 42, - } - i.set("foobar", service) - - count := 0 - - i.forEach(func(name string, service any) { - is.Equal("foobar", name) - count++ - }) - - is.Equal(1, count) -} - -func TestInjectorServiceNotFound(t *testing.T) { - is := assert.New(t) - - i := New() - - service1 := &ServiceEager[int]{ - name: "foo", - instance: 42, - } - - service2 := &ServiceEager[int]{ - name: "bar", - instance: 21, - } - - i.set("foo", service1) - i.set("bar", service2) - is.Len(i.services, 2) - - err := i.serviceNotFound("hello") - is.ErrorContains(err, "DI: could not find service `hello`, available services:") - is.ErrorContains(err, "`foo`") - is.ErrorContains(err, "`bar`") -} - -func TestInjectorOnServiceInvoke(t *testing.T) { - is := assert.New(t) - - i := New() - - i.onServiceInvoke("foo") - i.onServiceInvoke("bar") - - is.Equal(0, i.orderedInvocation["foo"]) - is.Equal(1, i.orderedInvocation["bar"]) - is.Equal(2, i.orderedInvocationIndex) -} - -func TestInjectorCloneEager(t *testing.T) { - is := assert.New(t) - - count := 0 - - // setup original container - i1 := New() - ProvideNamedValue(i1, "foobar", 42) - is.NotPanics(func() { - value := MustInvokeNamed[int](i1, "foobar") - is.Equal(42, value) - }) - - // clone container - i2 := i1.Clone() - // invoked instance is not reused - s1, err := InvokeNamed[int](i2, "foobar") - is.NoError(err) - is.Equal(42, s1) - - // service can be overridden - OverrideNamed(i2, "foobar", func(_ *Injector) (int, error) { - count++ - return 6 * 9, nil - }) - s2, err := InvokeNamed[int](i2, "foobar") - is.NoError(err) - is.Equal(54, s2) - is.Equal(1, count) -} - -func TestInjectorCloneLazy(t *testing.T) { - is := assert.New(t) - - count := 0 - - // setup original container - i1 := New() - ProvideNamed(i1, "foobar", func(_ *Injector) (int, error) { - count++ - return 42, nil - }) - is.NotPanics(func() { - value := MustInvokeNamed[int](i1, "foobar") - is.Equal(42, value) - }) - is.Equal(1, count) - - // clone container - i2 := i1.Clone() - // invoked instance is not reused - s1, err := InvokeNamed[int](i2, "foobar") - is.NoError(err) - is.Equal(42, s1) - is.Equal(2, count) - - // service can be overridden - OverrideNamed(i2, "foobar", func(_ *Injector) (int, error) { - count++ - return 6 * 9, nil - }) - s2, err := InvokeNamed[int](i2, "foobar") - is.NoError(err) - is.Equal(54, s2) - is.Equal(3, count) -} diff --git a/service_eager_test.go b/service_eager_test.go deleted file mode 100644 index 3c45aff..0000000 --- a/service_eager_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package do - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestServiceEagerName(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - _test := test{foobar: "foobar"} - - service1 := newServiceEager("foobar", 42) - is.Equal("foobar", service1.getName()) - - service2 := newServiceEager("foobar", _test) - is.Equal("foobar", service2.getName()) -} - -func TestServiceEagerInstance(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - _test := test{foobar: "foobar"} - - service1 := newServiceEager("foobar", _test) - is.Equal(&ServiceEager[test]{name: "foobar", instance: _test}, service1) - - instance1, err1 := service1.getInstance(nil) - is.Nil(err1) - is.Equal(_test, instance1) - - service2 := newServiceEager("foobar", 42) - is.Equal(&ServiceEager[int]{name: "foobar", instance: 42}, service2) - - instance2, err2 := service2.getInstance(nil) - is.Nil(err2) - is.Equal(42, instance2) -} diff --git a/service_lazy_test.go b/service_lazy_test.go deleted file mode 100644 index d800179..0000000 --- a/service_lazy_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package do - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -type lazyTest struct { - idx int - err error -} - -func (t *lazyTest) Shutdown() error { - return t.err -} - -func TestServiceLazyName(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - _test := test{foobar: "foobar"} - - provider1 := func(i *Injector) (int, error) { - return 42, nil - } - provider2 := func(i *Injector) (test, error) { - return _test, nil - } - - service1 := newServiceLazy("foobar", provider1) - is.Equal("foobar", service1.getName()) - - service2 := newServiceLazy("foobar", provider2) - is.Equal("foobar", service2.getName()) -} - -func TestServiceLazyInstance(t *testing.T) { - is := assert.New(t) - - type test struct { - foobar string - } - _test := test{foobar: "foobar"} - - provider1 := func(i *Injector) (int, error) { - return 42, nil - } - provider2 := func(i *Injector) (test, error) { - return _test, nil - } - provider3 := func(i *Injector) (int, error) { - panic("error") - } - provider4 := func(i *Injector) (int, error) { - panic(fmt.Errorf("error")) - } - provider5 := func(i *Injector) (int, error) { - return 42, fmt.Errorf("error") - } - - i := New() - - service1 := newServiceLazy("foobar", provider1) - instance1, err1 := service1.getInstance(i) - is.Nil(err1) - is.Equal(42, instance1) - - service2 := newServiceLazy("hello", provider2) - instance2, err2 := service2.getInstance(i) - is.Nil(err2) - is.Equal(_test, instance2) - - is.Panics(func() { - service3 := newServiceLazy("baz", provider3) - _, _ = service3.getInstance(i) - }) - - is.NotPanics(func() { - service4 := newServiceLazy("plop", provider4) - instance4, err4 := service4.getInstance(i) - is.NotNil(err4) - is.Empty(instance4) - expected := fmt.Errorf("error") - is.Equal(expected, err4) - }) - - is.NotPanics(func() { - service5 := newServiceLazy("plop", provider5) - instance5, err5 := service5.getInstance(i) - is.NotNil(err5) - is.Empty(instance5) - expected := fmt.Errorf("error") - is.Equal(expected, err5) - }) -} - -func TestServiceLazyInstanceShutDown(t *testing.T) { - is := assert.New(t) - - index := 1 - provider1 := func(i *Injector) (*lazyTest, error) { - index++ - return &lazyTest{index, nil}, nil - } - provider2 := func(i *Injector) (*lazyTest, error) { - index++ - return &lazyTest{index, assert.AnError}, nil - } - - i := New() - - service1 := newServiceLazy("foobar", provider1) - instance1, err := service1.getInstance(i) - is.Nil(err) - is.True(service1.(*ServiceLazy[*lazyTest]).built) - err = service1.shutdown() - is.False(service1.(*ServiceLazy[*lazyTest]).built) - is.Nil(err) - instance2, err := service1.getInstance(i) - is.Nil(err) - is.NotEqual(instance1.idx, instance2.idx) - is.Equal(instance1.idx+1, instance2.idx) - - service2 := newServiceLazy("foobar", provider2).(*ServiceLazy[*lazyTest]) - is.False(service2.built) - is.Nil(err) - err = service2.build(i) - is.Nil(err) - is.True(service2.built) - err = service2.shutdown() - is.Error(assert.AnError, err) - is.True(service2.built) -} diff --git a/service_test.go b/service_test.go deleted file mode 100644 index 3741658..0000000 --- a/service_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package do - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestGenerateServiceName(t *testing.T) { - is := assert.New(t) - - type test struct{} //nolint:unused - - name := generateServiceName[test]() - is.Equal("do.test", name) - - name = generateServiceName[*test]() - is.Equal("*do.test", name) - - name = generateServiceName[int]() - is.Equal("int", name) -} diff --git a/utils_test.go b/utils_test.go deleted file mode 100644 index f576e60..0000000 --- a/utils_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package do - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestUtilsEmpty(t *testing.T) { - is := assert.New(t) - - value1 := empty[int]() - is.Empty(value1) - - value2 := empty[*int]() - is.Nil(value2) - is.Empty(value2) -} - -func TestUtilsMust(t *testing.T) { - is := assert.New(t) - - is.Panics(func() { - must(fmt.Errorf("error")) - }) - is.NotPanics(func() { - must(nil) - }) -}