public void AsyncScopedLifestyleDispose_WithWhenScopeEndsRegistration_CallsTheRegisteredAction()
        {
            // Arrange
            int actionCallCount = 0;

            var container = new Container();

            var lifestyle = new AsyncScopedLifestyle();

            container.Register <DisposableCommand, DisposableCommand>(lifestyle);

            container.RegisterInitializer <DisposableCommand>(command =>
            {
                lifestyle.WhenScopeEnds(container, () => { actionCallCount++; });
            });

            var scope = AsyncScopedLifestyle.BeginScope(container);

            try
            {
                container.GetInstance <DisposableCommand>();
            }
            finally
            {
                // Act
                scope.Dispose();
            }

            // Assert
            Assert.AreEqual(1, actionCallCount, "Delegate is expected to be called exactly once.");
        }
        public void WhenScopeEnds_NullActionArgument_ThrowsException()
        {
            // Arrange
            Action invalidArgument = null;

            var lifestyle = new AsyncScopedLifestyle();

            // Act
            Action action = () => lifestyle.WhenScopeEnds(new Container(), invalidArgument);

            // Assert
            AssertThat.Throws <ArgumentNullException>(action);
        }
        public void ContainerVerify_WithWhenScopeEndsRegistration_Succeeds()
        {
            // Arrange
            var container = new Container();

            var lifestyle = new AsyncScopedLifestyle();

            container.Register <ICommand, DisposableCommand>(lifestyle);

            container.RegisterInitializer <DisposableCommand>(command =>
            {
                lifestyle.WhenScopeEnds(container, () => { });
            });

            // Act
            container.Verify();
        }
        public void AsyncScopedLifestyleDispose_WithWhenScopeEndsRegistration_CallsTheRegisteredActionBeforeCallingDispose()
        {
            // Arrange
            bool delegateHasBeenCalled          = false;
            DisposableCommand instanceToDispose = null;

            var container = new Container();

            var lifestyle = new AsyncScopedLifestyle();

            container.Register <DisposableCommand>(lifestyle);

            container.RegisterInitializer <DisposableCommand>(command =>
            {
                lifestyle.WhenScopeEnds(container, () =>
                {
                    Assert.IsFalse(command.HasBeenDisposed,
                                   "The action should be called before disposing the instance, because users are " +
                                   "to use those instances.");
                    delegateHasBeenCalled = true;
                });
            });

            var scope = AsyncScopedLifestyle.BeginScope(container);

            try
            {
                instanceToDispose = container.GetInstance <DisposableCommand>();
            }
            finally
            {
                // Act
                scope.Dispose();
            }

            // Assert
            Assert.IsTrue(delegateHasBeenCalled, "Delegate is expected to be called.");
        }
        public void WhenScopeEnds_CalledOutOfTheContextOfAAsyncScopedLifestyle_ThrowsException()
        {
            // Arrange
            var lifestyle = new AsyncScopedLifestyle();

            var container = new Container();

            container.Register <ConcreteCommand>(new AsyncScopedLifestyle());

            try
            {
                // Act
                lifestyle.WhenScopeEnds(container, () => { });

                // Assert
                Assert.Fail("Exception expected.");
            }
            catch (InvalidOperationException ex)
            {
                Assert.IsTrue(ex.Message.Contains(
                                  "This method can only be called within the context of an active (Async Scoped) scope."),
                              "Actual: " + ex.Message);
            }
        }