using System.Linq; using Shouldly; using Volo.DependencyInjection; using Xunit; namespace Microsoft.Extensions.DependencyInjection { public class AbpConventionalDependencyInjectionExtensions_Tests { private readonly IServiceCollection _services; public AbpConventionalDependencyInjectionExtensions_Tests() { _services = new ServiceCollection(); } [Fact] public void Should_Register_Transient() { //Act _services.AddType(typeof(MyTransientClass)); //Assert _services.ShouldContainTransient(typeof(MyTransientClass)); } [Fact] public void Should_Register_Singleton() { //Act _services.AddType(typeof(MySingletonClass)); //Assert _services.ShouldContainSingleton(typeof(MySingletonClass)); } [Fact] public void Should_Register_Scoped() { //Act _services.AddType(typeof(MyScopedClass)); //Assert _services.ShouldContainScoped(typeof(MyScopedClass)); } [Fact] public void Should_Register_Scoped_With_Dependency_Attribute() { //Act _services.AddType(typeof(MyScopedClassWithDependencyAttribute)); //Assert _services.ShouldContainScoped(typeof(MyScopedClassWithDependencyAttribute)); } [Fact] public void Dependency_Attribute_Should_Override_Interface_Lifetimes() { //Act _services.AddType(typeof(MyScopedClassWithDependencyAttribute2)); //Assert _services.ShouldContainScoped(typeof(MyScopedClassWithDependencyAttribute2)); } [Fact] public void Should_Register_For_Exposed_Services() { //Act _services.AddType(typeof(MyServiceWithExposeList)); //Assert _services.ShouldContain(typeof(IMyService1), typeof(MyServiceWithExposeList), ServiceLifetime.Transient); _services.ShouldContain(typeof(IMyService2), typeof(MyServiceWithExposeList), ServiceLifetime.Transient); _services.ShouldNotContainService(typeof(MyServiceWithExposeList)); } [Fact] public void Should_Register_Multiple_Implementation_For_Same_Service() { //Act _services.AddTypes(typeof(FirstImplOfMyService), typeof(SecondImplOfMyService)); //Assert //Check descriptons in service collection var descriptions = _services.Where(s => s.ServiceType == typeof(IMyService)).ToList(); descriptions.Count.ShouldBe(2); descriptions[0].ImplementationType.ShouldBe(typeof(FirstImplOfMyService)); descriptions[1].ImplementationType.ShouldBe(typeof(SecondImplOfMyService)); //Check from service provider var serviceProvider = _services.BuildServiceProvider(); //Default service should be second one serviceProvider.GetRequiredService().ShouldBeOfType(typeof(SecondImplOfMyService)); //Should also get all services var instances = serviceProvider.GetServices().ToList(); instances.Count.ShouldBe(2); instances[0].ShouldBeOfType(typeof(FirstImplOfMyService)); instances[1].ShouldBeOfType(typeof(SecondImplOfMyService)); } [Fact] public void Should_Not_Register_Second_Implementation_For_Same_Service_If_Second_Is_Marked_As_TryRegister() { //Act _services.AddTypes(typeof(FirstImplOfMyService), typeof(TryRegisterImplOfMyService)); //Assert //Check descriptons in service collection var descriptions = _services.Where(s => s.ServiceType == typeof(IMyService)).ToList(); descriptions.Count.ShouldBe(1); descriptions[0].ImplementationType.ShouldBe(typeof(FirstImplOfMyService)); //Check from service provider var serviceProvider = _services.BuildServiceProvider(); //Default service should be second one serviceProvider.GetRequiredService().ShouldBeOfType(typeof(FirstImplOfMyService)); //Should also get all services var instances = serviceProvider.GetServices().ToList(); instances.Count.ShouldBe(1); instances[0].ShouldBeOfType(typeof(FirstImplOfMyService)); } [Fact] public void Should_Replace_First_Implementation_By_Second_If_Second_Marked_As_ReplaceServices() { //Act _services.AddTypes(typeof(FirstImplOfMyService), typeof(MyServiceReplacesIMyService)); //Assert //Check descriptons in service collection var descriptions = _services.Where(s => s.ServiceType == typeof(IMyService)).ToList(); descriptions.Count.ShouldBe(1); descriptions[0].ImplementationType.ShouldBe(typeof(MyServiceReplacesIMyService)); //Check from service provider var serviceProvider = _services.BuildServiceProvider(); //Default service should be second one serviceProvider.GetRequiredService().ShouldBeOfType(typeof(MyServiceReplacesIMyService)); //Should also get all services var instances = serviceProvider.GetServices().ToList(); instances.Count.ShouldBe(1); instances[0].ShouldBeOfType(typeof(MyServiceReplacesIMyService)); } [Fact] public void Should_Not_Register_Classes_Marked_With_DisableConventionalRegistration() { _services.AddType(typeof(NonConventionalImplOfMyService)); _services.ShouldNotContainService(typeof(IMyService)); _services.ShouldNotContainService(typeof(NonConventionalImplOfMyService)); } [Fact] public void AddObjectAccessor_Test() { //Arrange var obj = new MyEmptyClass(); //Act var accessor = _services.AddObjectAccessor(); accessor.Value = obj; //Assert _services.GetSingletonInstance>().Value.ShouldBe(obj); _services.GetSingletonInstance>().Value.ShouldBe(obj); var serviceProvider = _services.BuildServiceProvider(); serviceProvider.GetRequiredService>().Value.ShouldBe(obj); serviceProvider.GetRequiredService>().Value.ShouldBe(obj); } public class MyTransientClass : ITransientDependency { } public class MySingletonClass : ISingletonDependency { } public class MyScopedClass : IScopedDependency { } [Dependency(ServiceLifetime.Scoped)] public class MyScopedClassWithDependencyAttribute { } [Dependency(ServiceLifetime.Scoped)] //Attribute overrides interface public class MyScopedClassWithDependencyAttribute2 : ITransientDependency { } public interface IMyService1 { } public interface IMyService2 { } [ExposeServices(typeof(IMyService1), typeof(IMyService2))] public class MyServiceWithExposeList : IMyService1, IMyService2, ITransientDependency { } [Dependency(ReplaceServices = true)] public class MyServiceReplacesIMyService : IMyService { } public interface IMyService : ITransientDependency { } public class FirstImplOfMyService : IMyService { } public class SecondImplOfMyService : IMyService { } [Dependency(TryRegister = true)] public class TryRegisterImplOfMyService : IMyService { } [DisableConventionalRegistration] public class NonConventionalImplOfMyService : IMyService { } public class MyEmptyClass { } } }