public void Dispose_ScopedInstanceResolvedDuringDisposingScope_DisposesThisInstanceLast()
        {
            // Arrange
            var disposedObjects = new List <object>();

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register <IPlugin>(() => new DisposablePlugin(disposedObjects.Add), scopedLifestyle);
            container.Register <IDisposable>(() => new DisposableObject(disposedObjects.Add), scopedLifestyle);
            container.Register <DisposableObject>(() => new DisposableObject(_ =>
            {
                container.GetInstance <IPlugin>();
            }), scopedLifestyle);

            container.GetInstance <IDisposable>();
            container.GetInstance <DisposableObject>();

            // Act
            scope.Dispose();

            // Assert
            Assert.IsInstanceOfType(disposedObjects.Last(), typeof(DisposablePlugin),
                                    "Since the disposable logger is requested during disposal of the scope, it should be " +
                                    "disposed after all other already created services have been disposed. " +
                                    "In the given case, disposing DisposableLogger before the IDisposable registration becomes " +
                                    "a problem when that registration starts using ILogger in its dispose method as well.");
        }
        public void Dispose_RecursiveResolveTriggeredDuringEndScopeAction_ThrowsDescriptiveException()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register <IPlugin>(() =>
            {
                scope.WhenScopeEnds(() =>
                {
                    container.GetInstance <IPlugin>();
                });

                return(new DisposablePlugin());
            });

            container.GetInstance <IPlugin>();

            // Act
            Action action = () => scope.Dispose();

            // Assert
            AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(@"
                The registered delegate for type IPlugin threw an exception. A recursive registration of 
                Action or IDisposable instances was detected during disposal of the scope. 
                This is possibly caused by a component that is directly or indirectly depending on itself"
                                                                                .TrimInside(),
                                                                                action);
        }
        public void Dispose_InstanceResolvedDuringDisposingScopeRegisteringEndAction_CallsThisAction()
        {
            // Arrange
            bool actionCalled = false;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register <DisposableObject>(() => new DisposableObject(_ =>
            {
                container.GetInstance <IPlugin>();
            }), scopedLifestyle);

            container.Register <IPlugin>(() =>
            {
                scope.WhenScopeEnds(() => actionCalled = true);
                return(new DisposablePlugin());
            }, Lifestyle.Transient);

            container.GetInstance <DisposableObject>();

            // Act
            scope.Dispose();

            // Assert
            Assert.IsTrue(actionCalled);
        }
예제 #4
0
        public void GetCurrentScope_CalledDuringVerificationOnADifferentThread_ReturnsARealScope()
        {
            // Arrange
            Scope backgroundRequestedScope = null;
            Task  task = null;

            var container = new Container();

            var scope     = new Scope();
            var lifestyle = new FakeScopedLifestyle(scope);

            container.Register <IPlugin, DisposablePlugin>(lifestyle);
            container.RegisterInitializer <DisposablePlugin>(p =>
            {
                // Resolve on a different thread (so not during verification)
                task = Task.Run(() =>
                {
                    backgroundRequestedScope = lifestyle.GetCurrentScope(container);
                });

                Thread.Sleep(150);
            });

            // Act
            container.Verify();

            task.Wait();

            // Assert
            Assert.AreSame(scope, backgroundRequestedScope,
                           "Since the background thread does not run verify, the returned scope should not be the " +
                           "verification scope.");
        }
        public void Dispose_ScopedInstanceResolvedDuringDisposingScope_CreatesInstanceWithExpectedLifestyle()
        {
            // Arrange
            IPlugin plugin1 = null;
            IPlugin plugin2 = null;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register <IPlugin>(() => new DisposablePlugin(), scopedLifestyle);

            container.Register <DisposableObject>(() => new DisposableObject(disposing: _ =>
            {
                plugin1 = container.GetInstance <IPlugin>();
                plugin2 = container.GetInstance <IPlugin>();
            }), scopedLifestyle);

            container.GetInstance <DisposableObject>();

            // Act
            scope.Dispose();

            // Assert
            Assert.IsNotNull(plugin1);
            Assert.AreSame(plugin1, plugin2);
        }
예제 #6
0
        public void Verify_ExecutedWithinActiveScope_CreatesScopedInstancesInItsOwnScope()
        {
            // Arrange
            DisposablePlugin plugin = null;

            var container = new Container();

            container.Options.EnableAutoVerification = false;

            var scopedLifestyle = new FakeScopedLifestyle(new Scope(container));

            container.Register <ServiceDependingOn <IPlugin> >();
            container.Register <IPlugin, DisposablePlugin>(scopedLifestyle);
            container.RegisterInitializer <DisposablePlugin>(p => plugin = p);

            // By resolving IPlugin here, it becomes cached within the created Scope.
            container.GetInstance <IPlugin>();
            plugin = null;

            // Act
            // When calling verify, we expect DisposablePlugin to be created again, because verify gets its own scope
            container.Verify();

            // Assert
            Assert.IsNotNull(plugin);
        }
        public void GetCurrentScope_CalledOutsideOfVerification_ReturnsNull()
        {
            // Arrange
            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            // Act
            var actualScope = scopedLifestyle.GetCurrentScope(new Container());

            // Assert
            Assert.IsNull(actualScope);
        }
        public void Verify_VerifyingAScopedInstance_DisposesThatInstance()
        {
            // Arrange
            var disposable = new DisposableObject();

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register <IDisposable>(() => disposable, scopedLifestyle);

            // Act
            container.Verify();

            // Assert
            Assert.IsTrue(disposable.IsDisposedOnce);
        }
예제 #9
0
        public void Verify_ExecutedWithinActiveScope_DisposesThatInstanceWhenVerifyFinishes()
        {
            // Arrange
            DisposablePlugin plugin = null;

            var container = new Container();

            var lifestyle = new FakeScopedLifestyle(new Scope());

            container.Register <IPlugin, DisposablePlugin>(lifestyle);
            container.RegisterInitializer <DisposablePlugin>(p => plugin = p);

            // Act
            container.Verify();

            // Assert
            Assert.IsNotNull(plugin);
            Assert.IsTrue(plugin.IsDisposedOnce);
        }
        public void Dispose_RecursiveResolveTriggeredDuringEndScopeAction_StillDisposesRegisteredDisposables()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            var disposable = new DisposableObject();

            scope.RegisterForDisposal(disposable);

            container.Register <IPlugin>(() =>
            {
                scope.WhenScopeEnds(() =>
                {
                    container.GetInstance <IPlugin>();
                });

                return(new DisposablePlugin());
            });

            container.GetInstance <IPlugin>();

            try
            {
                // Act
                scope.Dispose();

                Assert.Fail("Exception expected.");
            }
            catch
            {
                // Assert
                Assert.IsTrue(disposable.IsDisposedOnce,
                              "Even though there was a recursion detected when executing Action delegates, all " +
                              "registered disposables should still get disposed.");
            }
        }
예제 #11
0
        public void GetInstance_ResolvingScopedInstanceWhileDifferentThreadIsVerifying_DoesNotResolveInstanceFromVerificationScope()
        {
            // Arrange
            DisposablePlugin verifiedPlugin           = null;
            DisposablePlugin backgroundResolvedPlugin = null;
            Task             task = null;

            var container = new Container();

            var scope     = new Scope();
            var lifestyle = new FakeScopedLifestyle(scope);

            container.Register <IPlugin, DisposablePlugin>(lifestyle);
            container.RegisterInitializer <DisposablePlugin>(p =>
            {
                verifiedPlugin = p;

                // Resolve on a different thread (so not during verification)
                task = Task.Run(() =>
                {
                    backgroundResolvedPlugin = (DisposablePlugin)container.GetInstance <IPlugin>();
                });

                Thread.Sleep(150);
            });

            // Act
            container.Verify();

            task.Wait();

            // Assert
            Assert.IsFalse(backgroundResolvedPlugin.IsDisposedOnce,
                           "Since this instance isn't resolved during verification, but within an active scope, " +
                           "The instance should not have been disposed here.");

            scope.Dispose();

            Assert.IsTrue(backgroundResolvedPlugin.IsDisposedOnce, "Now it should have been disposed.");
        }
        public void GetCurrentScope_CalledDuringVerification_ReturnsAScope()
        {
            // Arrange
            Scope scopeDuringVerification = null;

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register <IDisposable>(() => new DisposableObject(), scopedLifestyle);

            container.RegisterInitializer <IDisposable>(_ =>
            {
                scopeDuringVerification = scopedLifestyle.GetCurrentScope(container);
            });

            // Act
            container.Verify();

            // Assert
            Assert.IsNotNull(scopeDuringVerification);
        }
        public void Verify_RegisterForDisposalCalledDuringVerification_EnsuresDisposalOfRegisteredDisposable()
        {
            // Arrange
            var disposable = new DisposableObject();

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register <IPlugin>(() => new DisposablePlugin());

            container.RegisterInitializer <IPlugin>(_ =>
            {
                scopedLifestyle.RegisterForDisposal(container, disposable);
            });

            // Act
            container.Verify();

            // Assert
            Assert.IsTrue(disposable.IsDisposedOnce);
        }
        public void GetInstance_CalledOnADisposedScope_ThrowsObjectDisposedException()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register <IPlugin>(() => new DisposablePlugin(), scopedLifestyle);

            container.GetInstance <IPlugin>();

            scope.Dispose();

            // Act
            Action action = () => container.GetInstance <IPlugin>();

            // Assert
            AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(
                "Cannot access a disposed object.",
                action);
        }
        public void Verify_WhenScopeEndsCalledDuringVerification_WontCallActionWhenFinished()
        {
            // Arrange
            bool actionCalled = false;

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register <IPlugin>(() => new DisposablePlugin());

            container.RegisterInitializer <IPlugin>(_ =>
            {
                scopedLifestyle.WhenScopeEnds(container, () => actionCalled = true);
            });

            // Act
            container.Verify();

            // Assert
            Assert.IsFalse(actionCalled,
                           "Any registered action delegates should not be called during verification " +
                           "(but registration should succeed). Users are allowed to do any ");
        }
        public void Dispose_ExceptionThrownDuringDisposalAfterResolvingNewInstance_DoesNotCallAnyNewActions()
        {
            // Arrange
            bool scopeEndActionCalled = false;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register <IPlugin>(() => new DisposablePlugin());
            container.RegisterInitializer <IPlugin>(
                plugin => scope.WhenScopeEnds(() => scopeEndActionCalled = true));

            container.Register <DisposableObject>(() => new DisposableObject(_ =>
            {
                container.GetInstance <IPlugin>();
                throw new Exception("Bang!");
            }), scopedLifestyle);

            try
            {
                // Act
                scope.Dispose();

                // Assert
                Assert.Fail("Exception expected.");
            }
            catch
            {
                Assert.IsFalse(scopeEndActionCalled,
                               "In case of an exception, no actions will be further executed. This lowers the change " +
                               "the new exceptions are thrown from other actions that cover up the original exception.");
            }
        }
        public void Dispose_RecursiveResolveTriggeredInDispose_ThrowsDescriptiveException()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register <IPlugin>(() =>
            {
                var plugin = new DisposablePlugin(disposing: _ =>
                {
                    // Recursive dependency
                    // Although really bad practice, this must not cause an infinit spin or a stackoverflow.
                    container.GetInstance <IPlugin>();
                });

                scope.RegisterForDisposal(plugin);

                return(plugin);
            });

            container.GetInstance <IPlugin>();

            // Act
            Action action = () => scope.Dispose();

            // Assert
            AssertThat.ThrowsWithExceptionMessageContains <ActivationException>(@"
                The registered delegate for type IPlugin threw an exception. A recursive registration of 
                Action or IDisposable instances was detected during disposal of the scope. 
                This is possibly caused by a component that is directly or indirectly depending on itself"
                                                                                .TrimInside(),
                                                                                action);
        }
예제 #18
0
        public void GetCurrentScope_CalledOnSameThreadDuringVerification_ReturnsTheVerificationScope()
        {
            // Arrange
            Scope verificationScope = null;

            var container = new Container();

            var scope           = new Scope();
            var scopedLifestyle = new FakeScopedLifestyle(scope);

            container.Register <IPlugin, DisposablePlugin>(scopedLifestyle);
            container.RegisterInitializer <DisposablePlugin>(p =>
            {
                verificationScope = scopedLifestyle.GetCurrentScope(container);
            });

            // Act
            // When calling verify, we expect DisposablePlugin to be created again.
            container.Verify();

            // Assert
            Assert.AreNotSame(verificationScope, scope);
            Assert.IsTrue(verificationScope.ToString().Contains("VerificationScope"));
        }
        public void Dispose_ExceptionThrownDuringDisposalAfterResolvingNewInstance_DisposesThatInstance()
        {
            // Arrange
            bool newlyResolvedInstanceDisposed = false;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            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);
            }
        }
예제 #20
0
        public void GetCurrentScope_CalledDuringVerification_ReturnsAScope()
        {
            // Arrange
            Scope scopeDuringVerification = null;

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register<IDisposable>(() => new DisposableObject(), scopedLifestyle);

            container.RegisterInitializer<IDisposable>(_ =>
            {
                scopeDuringVerification = scopedLifestyle.GetCurrentScope(container);
            });

            // Act
            container.Verify();

            // Assert
            Assert.IsNotNull(scopeDuringVerification);
        }
예제 #21
0
        public void Dispose_ScopedInstanceResolvedDuringDisposingScope_CreatesInstanceWithExpectedLifestyle()
        {
            // Arrange
            IPlugin plugin1 = null;
            IPlugin plugin2 = null;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register<IPlugin>(() => new DisposablePlugin(), scopedLifestyle);

            container.Register<DisposableObject>(() => new DisposableObject(disposing: _ =>
            {
                plugin1 = container.GetInstance<IPlugin>();
                plugin2 = container.GetInstance<IPlugin>();
            }), scopedLifestyle);

            container.GetInstance<DisposableObject>();

            // Act
            scope.Dispose();

            // Assert
            Assert.IsNotNull(plugin1);
            Assert.AreSame(plugin1, plugin2);
        }
예제 #22
0
        public void Dispose_InstanceResolvedDuringDisposingScopeRegisteringEndAction_CallsThisAction()
        {
            // Arrange
            bool actionCalled = false;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register<DisposableObject>(() => new DisposableObject(_ =>
            {
                container.GetInstance<IPlugin>();
            }), scopedLifestyle);

            container.Register<IPlugin>(() =>
            {
                scope.WhenScopeEnds(() => actionCalled = true);
                return new DisposablePlugin();
            }, Lifestyle.Transient);

            container.GetInstance<DisposableObject>();

            // Act
            scope.Dispose();

            // Assert
            Assert.IsTrue(actionCalled);
        }
예제 #23
0
        public void Dispose_ExceptionThrownDuringDisposalAfterResolvingNewInstance_DoesNotCallAnyNewActions()
        {
            // Arrange
            bool scopeEndActionCalled = false;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register<IPlugin>(() => new DisposablePlugin());
            container.RegisterInitializer<IPlugin>(
                plugin => scope.WhenScopeEnds(() => scopeEndActionCalled = true));

            container.Register<DisposableObject>(() => new DisposableObject(_ =>
            {
                container.GetInstance<IPlugin>();
                throw new Exception("Bang!");
            }), scopedLifestyle);

            try
            {
                // Act
                scope.Dispose();

                // Assert
                Assert.Fail("Exception expected.");
            }
            catch
            {
                Assert.IsFalse(scopeEndActionCalled,
                    "In case of an exception, no actions will be further executed. This lowers the change " +
                    "the new exceptions are thrown from other actions that cover up the original exception.");
            }
        }
예제 #24
0
        public void GetInstance_ResolvingScopedInstanceWhileDifferentThreadIsVerifying_DoesNotResolveInstanceFromVerificationScope()
        {
            // Arrange
            DisposablePlugin verifiedPlugin = null;
            DisposablePlugin backgroundResolvedPlugin = null;
            Task task = null;

            var container = new Container();

            var scope = new Scope();
            var lifestyle = new FakeScopedLifestyle(scope);

            container.Register<IPlugin, DisposablePlugin>(lifestyle);
            container.RegisterInitializer<DisposablePlugin>(p =>
            {
                verifiedPlugin = p;

                // Resolve on a different thread (so not during verification)
                task = Task.Run(() =>
                {
                    backgroundResolvedPlugin = (DisposablePlugin)container.GetInstance<IPlugin>();
                });

                Thread.Sleep(150);
            });

            // Act
            container.Verify();

            task.Wait();

            // Assert
            Assert.IsFalse(backgroundResolvedPlugin.IsDisposedOnce,
                "Since this instance isn't resolved during verification, but within an active scope, " +
                "The instance should not have been disposed here.");

            scope.Dispose();

            Assert.IsTrue(backgroundResolvedPlugin.IsDisposedOnce, "Now it should have been disposed.");
        }
예제 #25
0
        public void Verify_ExecutedWithinActiveScope_DisposesThatInstanceWhenVerifyFinishes()
        {
            // Arrange
            DisposablePlugin plugin = null;

            var container = new Container();

            var lifestyle = new FakeScopedLifestyle(new Scope());

            container.Register<IPlugin, DisposablePlugin>(lifestyle);
            container.RegisterInitializer<DisposablePlugin>(p => plugin = p);

            // Act
            container.Verify();

            // Assert
            Assert.IsNotNull(plugin);
            Assert.IsTrue(plugin.IsDisposedOnce);
        }
예제 #26
0
        public void GetCurrentScope_CalledOnSameThreadDuringVerification_ReturnsTheVerificationScope()
        {
            // Arrange
            Scope verificationScope = null;

            var container = new Container();

            var scope = new Scope();
            var scopedLifestyle = new FakeScopedLifestyle(scope);

            container.Register<IPlugin, DisposablePlugin>(scopedLifestyle);
            container.RegisterInitializer<DisposablePlugin>(p =>
            {
                verificationScope = scopedLifestyle.GetCurrentScope(container);
            });

            // Act
            // When calling verify, we expect DisposablePlugin to be created again.
            container.Verify();

            // Assert
            Assert.AreNotSame(verificationScope, scope);
            Assert.IsTrue(verificationScope.ToString().Contains("VerificationScope"));
        }
예제 #27
0
        public void Verify_WhenScopeEndsCalledDuringVerification_WontCallActionWhenFinished()
        {
            // Arrange
            bool actionCalled = false;

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register<IPlugin>(() => new DisposablePlugin());

            container.RegisterInitializer<IPlugin>(_ =>
            {
                scopedLifestyle.WhenScopeEnds(container, () => actionCalled = true);
            });

            // Act
            container.Verify();

            // Assert
            Assert.IsFalse(actionCalled,
                "Any registered action delegates should not be called during verification " +
                "(but registration should succeed). Users are allowed to do any ");
        }
예제 #28
0
        public void Verify_RegisterForDisposalCalledDuringVerification_EnsuresDisposalOfRegisteredDisposable()
        {
            // Arrange
            var disposable = new DisposableObject();

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register<IPlugin>(() => new DisposablePlugin());

            container.RegisterInitializer<IPlugin>(_ =>
            {
                scopedLifestyle.RegisterForDisposal(container, disposable);
            });

            // Act
            container.Verify();

            // Assert
            Assert.IsTrue(disposable.IsDisposedOnce);
        }
예제 #29
0
        public void Dispose_RecursiveResolveTriggeredDuringEndScopeAction_ThrowsDescriptiveException()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register<IPlugin>(() =>
            {
                scope.WhenScopeEnds(() =>
                {
                    container.GetInstance<IPlugin>();
                });

                return new DisposablePlugin();
            });

            container.GetInstance<IPlugin>();

            // Act
            Action action = () => scope.Dispose();

            // Assert
            AssertThat.ThrowsWithExceptionMessageContains<ActivationException>(@"
                The registered delegate for type IPlugin threw an exception. A recursive registration of 
                Action or IDisposable instances was detected during disposal of the scope. 
                This is possibly caused by a component that is directly or indirectly depending on itself"
                .TrimInside(),
                action);
        }
예제 #30
0
        public void GetCurrentScope_CalledDuringVerificationOnADifferentThread_ReturnsARealScope()
        {
            // Arrange
            Scope backgroundRequestedScope = null;
            Task task = null;

            var container = new Container();

            var scope = new Scope();
            var lifestyle = new FakeScopedLifestyle(scope);

            container.Register<IPlugin, DisposablePlugin>(lifestyle);
            container.RegisterInitializer<DisposablePlugin>(p =>
            {
                // Resolve on a different thread (so not during verification)
                task = Task.Run(() =>
                {
                    backgroundRequestedScope = lifestyle.GetCurrentScope(container);
                });

                Thread.Sleep(150);
            });

            // Act
            container.Verify();

            task.Wait();

            // Assert
            Assert.AreSame(scope, backgroundRequestedScope, 
                "Since the background thread does not run verify, the returned scope should not be the " +
                "verification scope.");
        }
예제 #31
0
        public void Dispose_RecursiveResolveTriggeredInDispose_ThrowsDescriptiveException()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register<IPlugin>(() =>
            {
                var plugin = new DisposablePlugin(disposing: _ =>
                {
                    // Recursive dependency
                    // Although really bad practice, this must not cause an infinit spin or a stackoverflow.
                    container.GetInstance<IPlugin>();
                });

                scope.RegisterForDisposal(plugin);

                return plugin;
            });

            container.GetInstance<IPlugin>();

            // Act
            Action action = () => scope.Dispose();

            // Assert
            AssertThat.ThrowsWithExceptionMessageContains<ActivationException>(@"
                The registered delegate for type IPlugin threw an exception. A recursive registration of 
                Action or IDisposable instances was detected during disposal of the scope. 
                This is possibly caused by a component that is directly or indirectly depending on itself"
                .TrimInside(),
                action);
        }
예제 #32
0
        public void GetCurrentScope_CalledOutsideOfVerification_ReturnsNull()
        {
            // Arrange
            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            // Act
            var actualScope = scopedLifestyle.GetCurrentScope(new Container());

            // Assert
            Assert.IsNull(actualScope);
        }
예제 #33
0
        public void Dispose_ExceptionThrownDuringDisposalAfterResolvingNewInstance_DisposesThatInstance()
        {
            // Arrange
            bool newlyResolvedInstanceDisposed = false;

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            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);
            }
        }
예제 #34
0
        public void GetInstance_CalledOnADisposedScope_ThrowsObjectDisposedException()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register<IPlugin>(() => new DisposablePlugin(), scopedLifestyle);

            container.GetInstance<IPlugin>();

            scope.Dispose();

            // Act
            Action action = () => container.GetInstance<IPlugin>();

            // Assert
            AssertThat.ThrowsWithExceptionMessageContains<ActivationException>(
                CannotAccessADisposedObjectMessage,
                action);
        }
예제 #35
0
        public void Dispose_ScopedInstanceResolvedDuringDisposingScope_DisposesThisInstanceLast()
        {
            // Arrange
            var disposedObjects = new List<object>();

            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            container.Register<IPlugin>(() => new DisposablePlugin(disposedObjects.Add), scopedLifestyle);
            container.Register<IDisposable>(() => new DisposableObject(disposedObjects.Add), scopedLifestyle);
            container.Register<DisposableObject>(() => new DisposableObject(_ =>
            {
                container.GetInstance<IPlugin>();
            }), scopedLifestyle);

            container.GetInstance<IDisposable>();
            container.GetInstance<DisposableObject>();

            // Act
            scope.Dispose();

            // Assert
            AssertThat.IsInstanceOfType(typeof(DisposablePlugin), disposedObjects.Last(), "Since the disposable logger is requested during disposal of the scope, it should be " +
                "disposed after all other already created services have been disposed. " +
                "In the given case, disposing DisposableLogger before the IDisposable registration becomes " +
                "a problem when that registration starts using ILogger in its dispose method as well.");
        }
예제 #36
0
        public void Dispose_RecursiveResolveTriggeredDuringEndScopeAction_StillDisposesRegisteredDisposables()
        {
            // Arrange
            var scope = new Scope();

            var scopedLifestyle = new FakeScopedLifestyle(scope);

            var container = new Container();

            var disposable = new DisposableObject();

            scope.RegisterForDisposal(disposable);

            container.Register<IPlugin>(() =>
            {
                scope.WhenScopeEnds(() =>
                {
                    container.GetInstance<IPlugin>();
                });

                return new DisposablePlugin();
            });

            container.GetInstance<IPlugin>();

            try
            {
                // Act
                scope.Dispose();

                Assert.Fail("Exception expected.");
            }
            catch
            {
                // Assert
                Assert.IsTrue(disposable.IsDisposedOnce,
                    "Even though there was a recursion detected when executing Action delegates, all " +
                    "registered disposables should still get disposed.");
            }
        }
예제 #37
0
        public void Verify_ExecutedWithinActiveScope_CreatesScopedInstancesInItsOwnScope()
        {
            // Arrange
            DisposablePlugin plugin = null;

            var container = new Container();

            var scopedLifestyle = new FakeScopedLifestyle(new Scope());

            container.Register<ServiceDependingOn<IPlugin>>();
            container.Register<IPlugin, DisposablePlugin>(scopedLifestyle);
            container.RegisterInitializer<DisposablePlugin>(p => plugin = p);

            // By resolving IPlugin here, it becomes cached within the created Scope.
            container.GetInstance<IPlugin>();
            plugin = null;

            // Act
            // When calling verify, we expect DisposablePlugin to be created again.
            container.Verify();

            // Assert
            Assert.IsNotNull(plugin);
        }
예제 #38
0
        public void Verify_VerifyingAScopedInstance_DisposesThatInstance()
        {
            // Arrange
            var disposable = new DisposableObject();

            var scopedLifestyle = new FakeScopedLifestyle(scope: null);

            var container = new Container();

            container.Register<IDisposable>(() => disposable, scopedLifestyle);

            // Act
            container.Verify();

            // Assert
            Assert.IsTrue(disposable.IsDisposedOnce);
        }