コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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.");
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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.");
            }
        }
コード例 #7
0
        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);
            }
        }
コード例 #8
0
        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.");
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        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());
        }
コード例 #12
0
        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.");
            }
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        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);
        }
コード例 #15
0
        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.");
        }
コード例 #16
0
        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);
        }
コード例 #17
0
        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);
            }
        }
コード例 #18
0
        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);
            }
        }
コード例 #19
0
        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.");
        }
コード例 #20
0
        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);
            }
        }
コード例 #21
0
        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);
        }
コード例 #22
0
        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);
            }
        }
コード例 #23
0
        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.");
        }
コード例 #24
0
        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);
        }
コード例 #25
0
        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);
        }
コード例 #26
0
        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);
        }