namespace Syrette.Tests; public class ServiceContainerResolutionTests { [Fact(DisplayName = "GetService resolves a singleton registration")] public void GetService_T_resolves_singleton() { var container = new ServiceContainer(); container.AddSingleton(); var instance = container.GetService(); Assert.NotNull(instance); Assert.IsType(instance); } [Fact(DisplayName = "GetService resolves a transient registration")] public void GetService_T_resolves_transient() { var container = new ServiceContainer(); container.AddTransient(); var instance = container.GetService(); Assert.NotNull(instance); Assert.IsType(instance); } [Fact(DisplayName = "Multiple GetService calls for a singleton return the same instance")] public void Singleton_returns_same_instance() { var container = new ServiceContainer(); container.AddSingleton(); var a = container.GetService(); var b = container.GetService(); Assert.Same(a, b); } [Fact(DisplayName = "Multiple GetService calls for a transient return different instances")] public void Transient_returns_new_instance() { var container = new ServiceContainer(); container.AddTransient(); var a = container.GetService(); var b = container.GetService(); Assert.NotSame(a, b); } [Fact(DisplayName = "GetService(Type) non-generic overload resolves a registered service")] public void GetService_Type_non_generic_resolves() { var container = new ServiceContainer(); container.AddSingleton(); var instance = container.GetService(typeof(ITestService)); Assert.NotNull(instance); Assert.IsType(instance); } [Fact(DisplayName = "GetService(Type, object[]) passes resolution-time args to the constructor")] public void GetService_Type_with_args_resolves() { var container = new ServiceContainer(); container.AddTransient(); var instance = container.GetService(typeof(ITestService), new object[] { Guid.NewGuid() }); Assert.NotNull(instance); } [Fact(DisplayName = "GetService throws InvalidOperationException when type is not registered")] public void GetService_T_throws_for_unregistered() { var container = new ServiceContainer(); Assert.Throws(() => container.GetService()); } [Fact(DisplayName = "GetService(Type) throws InvalidOperationException when type is not registered")] public void GetService_Type_throws_for_unregistered() { var container = new ServiceContainer(); Assert.Throws(() => container.GetService(typeof(ITestService))); } [Fact(DisplayName = "TryGetService(Type) returns null when type is not registered")] public void TryGetService_returns_null_for_unregistered() { var container = new ServiceContainer(); var result = container.TryGetService(typeof(ITestService)); Assert.Null(result); } [Fact(DisplayName = "TryGetService(Type) returns an instance when the type is registered")] public void TryGetService_returns_instance_when_registered() { var container = new ServiceContainer(); container.AddSingleton(); var result = container.TryGetService(typeof(ITestService)); Assert.NotNull(result); } [Fact(DisplayName = "Resolving by implementation type works when only the interface was registered")] public void Resolve_by_implementation_type_when_not_registered_directly() { var container = new ServiceContainer(); container.AddSingleton(); var instance = container.GetService(typeof(TestServiceImpl)); Assert.NotNull(instance); } [Fact(DisplayName = "Resolution-time args override registration-time args of the same type")] public void Resolution_time_args_override_registration_time_args() { var container = new ServiceContainer(); container.AddSingleton(Guid.Empty); var resolved = container.GetService(typeof(ITestService), new object[] { Guid.NewGuid() }); Assert.NotNull(resolved); var deep = (TestDeepService)resolved; Assert.NotEqual(Guid.Empty, deep.Id); } [Fact(DisplayName = "GetServices returns instances of all registered implementations for a service type")] public void GetServices_returns_all_registered_implementations() { var container = new ServiceContainer(); container.AddSingleton(); container.AddSingleton(); var services = container.GetServices(); Assert.Equal(2, services.Count); var types = services.Select(s => s.GetType()).ToList(); Assert.Contains(typeof(TestServiceImpl), types); Assert.Contains(typeof(TestServiceAlt), types); } [Fact(DisplayName = "GetServiceTypes returns the implementation types of all registered services")] public void GetServiceTypes_returns_all_implementation_types() { var container = new ServiceContainer(); container.AddSingleton(); container.AddSingleton(); var types = container.GetServiceTypes(); Assert.Equal(2, types.Count); Assert.Contains(typeof(TestServiceImpl), types); Assert.Contains(typeof(TestServiceAlt), types); } }