public void GetInstance_OnInstanceRegisteredAsSingleton_ExpressionBuiltGetsFiredWithConstantExpression() { // Arrange var container = ContainerFactory.New(); container.Register <IUserRepository, SqlUserRepository>(Lifestyle.Singleton); Expression actualExpression = null; container.ExpressionBuilt += (sender, e) => { if (e.RegisteredServiceType == typeof(IUserRepository)) { actualExpression = e.Expression; } }; // Act container.GetInstance <IUserRepository>(); // Assert Assert.IsNotNull(actualExpression); AssertThat.IsInstanceOfType(typeof(ConstantExpression), actualExpression); }
public void GetAllInstances_RegistrationPrependedToExistingOpenGenericRegistration_ResolvesTheExtectedCollection() { // Arrange Type[] expectedHandlerTypes = new[] { typeof(StructEventHandler), typeof(NewConstraintEventHandler <StructEvent>), }; var container = ContainerFactory.New(); var registration = Lifestyle.Transient.CreateRegistration <StructEventHandler>(container); container.Collection.Append(typeof(IEventHandler <>), registration); container.Collection.Register(typeof(IEventHandler <>), new[] { typeof(NewConstraintEventHandler <>) }); // Act Type[] actualHandlerTypes = container.GetAllInstances(typeof(IEventHandler <StructEvent>)) .Select(h => h.GetType()).ToArray(); // Assert AssertThat.SequenceEquals(expectedHandlerTypes, actualHandlerTypes); }
public void RemoveExpressionBuilt_BeforeContainerHasBeenLocked_Succeeds() { // Arrange bool handlerCalled = false; var container = ContainerFactory.New(); EventHandler <ExpressionBuiltEventArgs> handler = (sender, e) => { handlerCalled = true; }; container.ExpressionBuilt += handler; container.RegisterSingleton <IUserRepository>(new SqlUserRepository()); // Act container.ExpressionBuilt -= handler; container.GetInstance <IUserRepository>(); // Assert Assert.IsFalse(handlerCalled, "The delegate was not removed correctly."); }
public void GetInstance_RequestingTypeDependingOnItself_ThrowsExceptionWithExpectedMessage() { // Arrange string expectedExcpetionMessage = @" The configuration is invalid. The type CyclicDependencyValidatorTests.A is directly or indirectly depending on itself." .TrimInside(); var container = ContainerFactory.New(); try { // Act // Note: A depends on B which depends on A. container.GetInstance <A>(); // Assert Assert.Fail("An exception was expected, because A depends indirectly on itself."); } catch (ActivationException ex) { AssertThat.StringContains(expectedExcpetionMessage, ex.Message); } }
public void GetInstance_OnDiagnosticErrorWithAutoVerificationEnabled_ShouldThrowExceptionExplainingAutoVerificationIsEnabled() { // Arrange var container = ContainerFactory.New(); container.Options.EnableAutoVerification = true; // Registering a Singleton service depending on a register Transient type ILogger container.Register <ServiceDependingOn <ILogger> >(Lifestyle.Singleton); container.Register <ILogger, NullLogger>(Lifestyle.Transient); container.Register <ICommand, ConcreteCommand>(); // Act Action action = () => container.GetInstance <ICommand>(); // Assert AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(@" Verification was triggered because Container.Options.EnableAutoVerification was enabled. To prevent the container from being verified on first resolve, set Container.Options.EnableAutoVerification to false." .TrimInside(), action); }
public void GetRegistration_UnregisteredConcreteTypeWithConstructorWithInvalidArguments_ThrowsExpectedException() { // Arrange var container = ContainerFactory.New(); try { // Act container.GetRegistration(typeof(RealUserService), throwOnFailure: true); // Assert Assert.Fail("Because we did not register the IUserRepository interface, " + "GetRegistration should fail."); } catch (ActivationException ex) { string message = ex.Message; AssertThat.ExceptionMessageContains(typeof(RealUserService).Name, ex, "The exception message should contain the name of the type."); AssertThat.ExceptionMessageContains(typeof(IUserRepository).Name, ex, "The exception message should contain the missing constructor argument."); AssertThat.ExceptionMessageContains( "Please ensure IUserRepository is registered", ex, "(1) The exception message should give a solution to solve the problem."); AssertThat.ExceptionMessageContains(@" Please ensure IUserRepository is registered, or change the constructor of RealUserService" .TrimInside(), ex, "(2) The exception message should give a solution to solve the problem."); } }
public void GetInstance_MultipleDelegatesHookedUpToEvent_FailsWhenBothDelegatesRegisterSameServiceType() { // Arrange string expectedMessage = "Multiple observers of the ResolveUnregisteredType event are " + "registering a delegate for the same service type"; var container = ContainerFactory.New(); container.ResolveUnregisteredType += (s, e) => e.Register(() => new SqlUserRepository()); container.ResolveUnregisteredType += (s, e) => e.Register(() => new InMemoryUserRepository()); try { // Act container.GetInstance <IUserRepository>(); // Assert Assert.Fail("Exception expected."); } catch (ActivationException ex) { AssertThat.StringContains(expectedMessage, ex.Message); } }
public void RegisterSingleByFunc_CallingGetInstanceMultipleTimes_WillOnlyCallDelegateOnce() { // Arrange const int ExpectedNumberOfCalles = 1; int actualNumberOfCalls = 0; var container = ContainerFactory.New(); container.RegisterSingle <IUserRepository>(() => { actualNumberOfCalls++; return(new SqlUserRepository()); }); // Act container.GetInstance <IUserRepository>(); container.GetInstance <IUserRepository>(); container.GetInstance <IUserRepository>(); // Assert Assert.AreEqual(ExpectedNumberOfCalles, actualNumberOfCalls, "The RegisterSingle method should register the object in such a way that the delegate will " + "only get called once during the lifetime of the application. Not more."); }
public void GetInstance_ConsumerDependingOnConditionalGenericRegistrationThatDoesNotGetInjected_ThrowsExpectedExceptions() { // Arrange var container = ContainerFactory.New(); container.RegisterConditional(typeof(IGeneric <>), typeof(GenericType <>), Lifestyle.Singleton, c => false); // Act Action action = () => container.GetInstance <ServiceWithDependency <IGeneric <int> > >(); // Assert AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(@" The constructor of type ServiceWithDependency<IGeneric<Int32>> contains the parameter with name 'dependency' and type IGeneric<Int32> that is not registered." .TrimInside(), action); AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(@" 1 conditional registration for IGeneric<T> exists that is applicable to IGeneric<Int32>, but its supplied predicate didn't return true when provided with the contextual information for ServiceWithDependency<IGeneric<Int32>>." .TrimInside(), action); }
public void Dispose_ExceptionThrownDuringDisposalAfterResolvingNewInstance_DisposesThatInstance() { // Arrange bool newlyResolvedInstanceDisposed = false; var container = ContainerFactory.New(); var scope = new Scope(container); var scopedLifestyle = new FakeScopedLifestyle(scope); container.Register <IPlugin>( () => new DisposablePlugin(disposing: _ => newlyResolvedInstanceDisposed = true), scopedLifestyle); container.Register <DisposableObject>(() => new DisposableObject(disposing: _ => { container.GetInstance <IPlugin>(); throw new Exception("Bang!"); }), scopedLifestyle); container.GetInstance <DisposableObject>(); try { // Act scope.Dispose(); // Assert Assert.Fail("Exception expected."); } catch { Assert.IsTrue(newlyResolvedInstanceDisposed); } }
public void GetInstance_OnInstanceRegisteredAsSingleton_ExpressionBuildingGetsFiredWithNewExpression() { // Arrange var container = ContainerFactory.New(); container.RegisterSingle <IUserRepository, SqlUserRepository>(); Expression actualExpression = null; container.ExpressionBuilding += (sender, e) => { if (e.RegisteredServiceType == typeof(IUserRepository)) { actualExpression = e.Expression; } }; // Act container.GetInstance <IUserRepository>(); // Assert Assert.IsNotNull(actualExpression); Assert.AreEqual("new SqlUserRepository()", actualExpression.ToString()); }
public void GetInstance_ThrowingDelegateRegisteredUsingRegisterByFunc_ThrowsActivationExceptionWithExpectedInnerException() { // Arrange var expectedInnerException = new InvalidOperationException(); var container = ContainerFactory.New(); container.Register <IUserRepository>(() => { throw expectedInnerException; }); try { // Act container.GetInstance <IUserRepository>(); // Assert Assert.Fail("The GetInstance method was expected to fail, because of the faulty registration."); } catch (ActivationException ex) { Assert.AreEqual(expectedInnerException, ex.InnerException, "The exception thrown by the registered delegate is expected to be wrapped in the " + "thrown ActivationException."); } }
public void GetAllInstances_AppendingInstancesOfClosedGenericImplementation_ResolvesTheExpectedCollection() { // Arrange Type[] expectedHandlerTypes = new[] { typeof(NewConstraintEventHandler <StructEvent>), typeof(AuditableEventEventHandler <StructEvent>), }; var container = ContainerFactory.New(); container.Collection.Register(typeof(IEventHandler <>), new[] { typeof(NewConstraintEventHandler <>) }); container.Collection .AppendInstance <IEventHandler <StructEvent> >(new AuditableEventEventHandler <StructEvent>()); // Act var handlers = container.GetAllInstances(typeof(IEventHandler <StructEvent>)); Type[] actualHandlerTypes = handlers.Select(h => h.GetType()).ToArray(); // Assert AssertThat.SequenceEquals(expectedHandlerTypes, actualHandlerTypes); }
public void GetAllInstances_MultipleOpenGenericTypesAppendedToPreRegistrationWithOpenGenericType_ResolvesTheExpectedCollection() { // Arrange Type[] expectedHandlerTypes = new[] { typeof(NewConstraintEventHandler <StructEvent>), typeof(StructConstraintEventHandler <StructEvent>), typeof(AuditableEventEventHandler <StructEvent>) }; var container = ContainerFactory.New(); container.Collection.Register(typeof(IEventHandler <>), new[] { typeof(NewConstraintEventHandler <>) }); container.Collection.Append(typeof(IEventHandler <>), typeof(StructConstraintEventHandler <>)); container.Collection.Append(typeof(IEventHandler <>), typeof(AuditableEventEventHandler <>)); // Act Type[] actualHandlerTypes = container.GetAllInstances(typeof(IEventHandler <StructEvent>)) .Select(h => h.GetType()).ToArray(); // Assert AssertThat.SequenceEquals(expectedHandlerTypes, actualHandlerTypes); }
public void ExpressionBuilt_OnInstanceWithInitializer_GetsExpressionWhereInitializerIsApplied() { // Arrange Expression actualBuiltExpression = null; var container = ContainerFactory.New(); container.Register <IUserRepository, SqlUserRepository>(); container.RegisterInitializer <SqlUserRepository>(repository => { }); container.ExpressionBuilt += (sender, e) => { Assert.AreEqual(e.RegisteredServiceType, typeof(IUserRepository), "Test setup fail."); actualBuiltExpression = e.Expression; }; // Act container.GetInstance <IUserRepository>(); // Assert AssertThat.IsNotInstanceOfType(typeof(NewExpression), actualBuiltExpression, "The initializer is expected to be applied BEFORE the ExpressionBuilt event ran."); }
public void GetInstance_GenericConditionalRegistrationThatOverlapsWithClosedRegistration_ThrowsExpectedException() { // Arrange var container = ContainerFactory.New(); container.Register <IGeneric <int>, IntGenericType>(); // Conditional that overlaps with previous registration. container.RegisterConditional(typeof(IGeneric <>), typeof(GenericType <>), c => true); // Act Action action = () => container.GetInstance <IGeneric <int> >(); // Assert AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(@" Multiple applicable registrations found for IGeneric<Int32>. The applicable registrations are (1) the unconditional closed generic registration for IGeneric<Int32> using IntGenericType and (2) the conditional open generic registration for IGeneric<T> using GenericType<T>. If your goal is to make one registration a fallback in case another registration is not applicable, make the fallback registration last and check the Handled property in the predicate." .TrimInside(), action); }
public void GetInstance_WithErrorInNestedDependency_ThrowsExceptionThatContainsAllTypes() { // Arrange var container = ContainerFactory.New(); container.Register <IUserRepository>(() => { throw new InvalidOperationException("Bla."); }); try { // Act container.GetInstance <RealUserService>(); Assert.Fail("This call is expected to fail, because RealUserService depends on IUserRepository."); } catch (ActivationException ex) { AssertThat.StringContains(typeof(RealUserService).Name, ex.Message); // Note: the next line is removed. We optimized Func<T> registrations, and because of this // we miss the information about that type. // AssertThat.StringContains(typeof(IUserRepository).Name, ex.Message); AssertThat.StringContains("Bla", ex.Message); } }
public void Verify_RegisteredCollectionWithNullElements_ThrowsException() { // Arrange var container = ContainerFactory.New(); IEnumerable <IUserRepository> repositories = new IUserRepository[] { null }; container.Collection.Register <IUserRepository>(repositories); try { // Act container.Verify(); // Assert Assert.Fail("Exception expected."); } catch (InvalidOperationException ex) { AssertThat.StringContains( "One of the items in the collection for type IUserRepository is a null reference.", ex.Message); } }
public void GetInstance_WithEventRegistered_RegistersExpectedDelegate() { // Arrange var expectedInstance = new SqlUserRepository(); var container = ContainerFactory.New(); container.ResolveUnregisteredType += (s, e) => { if (e.UnregisteredServiceType == typeof(IUserRepository)) { Func <object> repositoryCreator = () => expectedInstance; e.Register(repositoryCreator); } }; // Act var actualInstance = container.GetInstance <IUserRepository>(); // Assert Assert.AreEqual(expectedInstance, actualInstance, "The container did not return the expected instance."); }
public void Register_WithAnOverrideCalledAfterACallToVerify_FailsWithTheExpectedException() { // Arrange var container = ContainerFactory.New(); container.Options.AllowOverridingRegistrations = true; container.Register <IUserRepository, SqlUserRepository>(); container.Verify(); try { // Act container.Register <IUserRepository, SqlUserRepository>(Lifestyle.Singleton); // Assert Assert.Fail("Exception expected."); } catch (InvalidOperationException ex) { AssertThat.ExceptionMessageContains("The container can't be changed", ex); } }
public void InjectingEnumerableOfMetadata_ForDecoratedInstances_Succeeds() { // Arrange var container = ContainerFactory.New(); container.Collection.Append(typeof(IEventHandler<>), typeof(NotifyCustomer), Lifestyle.Singleton); container.Collection.Append(typeof(IEventHandler<>), typeof(DetermineNewWarehouseInventory)); container.RegisterDecorator(typeof(IEventHandler<>), typeof(EventHandlerDecorator<>)); // Act var service = container.GetInstance<EnumerableMetadata<IEventHandler<OrderShipped>>>(); container.Verify(); var metadatas = service.Metadatas; var notifyDecorator = (EventHandlerDecorator<OrderShipped>)metadatas.First().GetInstance(); var determineDecorator = (EventHandlerDecorator<OrderShipped>)metadatas.Last().GetInstance(); // Assert Assert.AreEqual(2, metadatas.Count()); AssertThat.IsInstanceOfType<NotifyCustomer>(notifyDecorator.Decoratee); AssertThat.IsInstanceOfType<DetermineNewWarehouseInventory>(determineDecorator.Decoratee); }
public void GetInstanceNonGeneric_UnregisteredConcreteTypeWithMultiplePublicConstructors_ThrowsExceptionWithExpectedMessage() { // Arrange string expectedMessage = "should contain exactly one public constructor, but it has 2."; var container = ContainerFactory.New(); try { // Act container.GetInstance(typeof(ConcreteTypeWithMultiplePublicConstructors)); // Assert Assert.Fail("Exception was expected."); } catch (ActivationException ex) { string actualMessage = ex.Message; Assert.IsTrue(actualMessage.Contains(expectedMessage), "The exception message should describe the actual problem. Actual message: " + actualMessage); } }
public void GetInstance_CalledMultipleTimesOnAnInvalidRegistrationOfSingletonFunc_ShouldNeverTriggerACyclicDependencyError() { // Arrange string expectedMessage = "The registered delegate for type ITimeProvider threw an exception."; var container = ContainerFactory.New(); // This registration will use a FuncSingletonInstanceProducer under the covers. container.Register <ITimeProvider>(() => { throw new NullReferenceException(); }, Lifestyle.Singleton); Action arrangeAction = () => container.GetInstance <ITimeProvider>(); AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(expectedMessage, arrangeAction, "Test setup failed."); // Act Action action = () => container.GetInstance <ITimeProvider>(); // Assert AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(expectedMessage, action, "Repeating calls to a failing FuncSingletonInstanceProducer should result in the same " + "exception being thrown every time."); }
public void GetInstance_RegisteredFuncWithInterceptor_CallsEventOnce() { // Arrange int expectedCallCount = 1; int actualCallCount = 0; var container = ContainerFactory.New(); container.Register <IUserRepository>(() => new SqlUserRepository(), Lifestyle.Singleton); container.ExpressionBuilt += (sender, e) => { if (e.RegisteredServiceType == typeof(IUserRepository)) { actualCallCount++; } }; // Act container.GetInstance <IUserRepository>(); // Assert Assert.AreEqual(expectedCallCount, actualCallCount); }
public void GetInstance_RegisteredTransient_CallsEventOnceForGivenServiceType() { // Arrange int expectedCallCount = 1; int actualCallCount = 0; var container = ContainerFactory.New(); container.Register <IUserRepository, SqlUserRepository>(); container.ExpressionBuilding += (sender, e) => { if (e.KnownImplementationType == typeof(SqlUserRepository)) { actualCallCount++; } }; // Act container.GetInstance <IUserRepository>(); // Assert Assert.AreEqual(expectedCallCount, actualCallCount); }
public void GetInstance_CalledForDecoratedCollection_CallsEventForBothTheInstanceAndTheDecorator() { // Arrange var actualContexts = new List <InstanceInitializationData>(); var container = ContainerFactory.New(); container.Collection.Register <ICommandHandler <RealCommand> >(new[] { typeof(StubCommandHandler) }); container.RegisterInitializer(actualContexts.Add, TruePredicate); container.RegisterDecorator(typeof(ICommandHandler <>), typeof(RealCommandHandlerDecorator)); // Act var decorator = container.GetAllInstances <ICommandHandler <RealCommand> >().Single() as RealCommandHandlerDecorator; // Assert // TODO: The container should actually call InstanceCreated for the IEnumerable<T> as well. Assert.AreEqual(2, actualContexts.Count, "Two event args were expected."); Assert.AreEqual(typeof(StubCommandHandler), actualContexts.First().Context.Registration.ImplementationType); Assert.AreEqual(typeof(RealCommandHandlerDecorator), actualContexts.Second().Context.Registration.ImplementationType); }