public void ExecuteTransaction_WhenCommandHasTransactionalAttribute()
        {
            var command = new FakeCommandWithoutValidator();

            Assert.IsAssignableFrom <ICommand>(command);

            var transactionProcessor = new Mock <IProcessTransactions>(MockBehavior.Strict);

            transactionProcessor.Setup(x => x.Execute());

            var decorated = new Mock <IHandleCommand <FakeCommandWithoutValidator> >(MockBehavior.Strict);
            var typeDescriptionProvider = TypeDescriptor.AddAttributes(decorated.Object.GetType(), new TransactionalAttribute());

            decorated.Setup(x => x.Handle(command));

            var decorator = new CommandTransactionDecorator <FakeCommandWithoutValidator>(transactionProcessor.Object, () => decorated.Object);

            decorator.Handle(command);

            decorated.Verify(x => x.Handle(command), Times.Once);
            transactionProcessor.Verify(x => x.Execute(), Times.Once);

            // Clean the provider for next test, or else it will fail - very odd.
            TypeDescriptor.RemoveProvider(typeDescriptionProvider, decorated.Object.GetType());
        }
        public void DoNotExecuteTransaction_WhenCommandDoNotHaveTransactionalAttribute()
        {
            var command = new FakeCommandWithoutValidator();
            Assert.IsAssignableFrom<ICommand>(command);

            var transactionProcessor = new Mock<IProcessTransactions>(MockBehavior.Strict);
            transactionProcessor.Setup(x => x.Execute());

            var decorated = new Mock<IHandleCommand<FakeCommandWithoutValidator>>(MockBehavior.Strict);
            decorated.Setup(x => x.Handle(command));

            var decorator = new CommandTransactionDecorator<FakeCommandWithoutValidator>(transactionProcessor.Object, () => decorated.Object);
            decorator.Handle(command);

            decorated.Verify(x => x.Handle(command), Times.Once);
            transactionProcessor.Verify(x => x.Execute(), Times.Never);
        }
        public void DoNotExecuteTransaction_WhenCommandDoNotHaveTransactionalAttribute()
        {
            var command = new FakeCommandWithoutValidator();

            Assert.IsAssignableFrom <ICommand>(command);

            var transactionProcessor = new Mock <IProcessTransactions>(MockBehavior.Strict);

            transactionProcessor.Setup(x => x.Execute());

            var decorated = new Mock <IHandleCommand <FakeCommandWithoutValidator> >(MockBehavior.Strict);

            decorated.Setup(x => x.Handle(command));

            var decorator = new CommandTransactionDecorator <FakeCommandWithoutValidator>(transactionProcessor.Object, () => decorated.Object);

            decorator.Handle(command);

            decorated.Verify(x => x.Handle(command), Times.Once);
            transactionProcessor.Verify(x => x.Execute(), Times.Never);
        }
        public void ExecuteTransaction_WhenCommandHasTransactionalAttribute()
        {
            var command = new FakeCommandWithoutValidator();
            Assert.IsAssignableFrom<ICommand>(command);

            var transactionProcessor = new Mock<IProcessTransactions>(MockBehavior.Strict);
            transactionProcessor.Setup(x => x.Execute());

            var decorated = new Mock<IHandleCommand<FakeCommandWithoutValidator>>(MockBehavior.Strict);
            var typeDescriptionProvider = TypeDescriptor.AddAttributes(decorated.Object.GetType(), new TransactionalAttribute());
            decorated.Setup(x => x.Handle(command));

            var decorator = new CommandTransactionDecorator<FakeCommandWithoutValidator>(transactionProcessor.Object, () => decorated.Object);
            decorator.Handle(command);

            decorated.Verify(x => x.Handle(command), Times.Once);
            transactionProcessor.Verify(x => x.Execute(), Times.Once);

            // Clean the provider for next test, or else it will fail - very odd.
            TypeDescriptor.RemoveProvider(typeDescriptionProvider, decorated.Object.GetType());
        }
        public void Handle_WithLogAttributeAndGloballyEnabled_ShouldLog(
            [Frozen] Mock<ICommandHandler<ICommand>> commandHandler,
            [Frozen] Mock<IUnitOfWork> unitOfWork,
            [Frozen] Mock<ILogger> logger,
            [Frozen] Mock<IAttributeFinder> attributeFinder,
            GlobalSettings settings,
            ICommand command,
            CommandTransactionDecorator<ICommand> decorator)
        {
            // Arrange and assert

            settings.EnableLogging = true;

            attributeFinder.Setup(f => f.Decorates(command.GetType(), typeof(TransactionalAttribute))).Returns(true);
            attributeFinder.Setup(f => f.Decorates(command.GetType(), typeof(LogAttribute))).Returns(true);

            // Act

            decorator.Handle(command);

            // Assert

            logger.Verify(l => l.Log(It.IsAny<string>()), Times.Exactly(2));
        }
        public void Handle_Exception_ShouldNotCommitUnitOfWork(
            [Frozen] Mock<ICommandHandler<ICommand>> commandHandler,
            [Frozen] Mock<IUnitOfWork> unitOfWork,
            [Frozen] Mock<ILogger> logger,
            [Frozen] Mock<IAttributeFinder> attributeFinder,
            ICommand command,
            CommandTransactionDecorator<ICommand> decorator)
        {
            // Arrange

            attributeFinder.Setup(f => f.Decorates(command.GetType(), typeof(TransactionalAttribute))).Returns(true);

            commandHandler.Setup(d => d.Handle(It.IsAny<ICommand>())).Throws<Exception>();

            // Act

            Assert.Throws<Exception>(() => decorator.Handle(command));

            // Assert

            unitOfWork.Verify(d => d.Clear(), Times.Once);

            unitOfWork.Verify(d => d.Commit(), Times.Never);
        }
        public void Handle_WithTransactionalAttributeAndNotGloballyEnabled_ShouldCommitAfterCommandHandled(
            [Frozen] Mock<ICommandHandler<ICommand>> commandHandler,
            [Frozen] Mock<IUnitOfWork> unitOfWork,
            [Frozen] Mock<ILogger> logger,
            [Frozen] Mock<IAttributeFinder> attributeFinder,
            [Frozen] GlobalSettings settings,
            ICommand command,
            CommandTransactionDecorator<ICommand> decorator)
        {
            // Arrange and assert

            settings.EnableTransactions = false;

            attributeFinder.Setup(f => f.Decorates(command.GetType(), typeof(TransactionalAttribute))).Returns(true);

            var callOrder = 0;

            unitOfWork.Setup(d => d.Clear()).Callback(() => callOrder++.Should().Be(0));
            commandHandler.Setup(d => d.Handle(command)).Callback(() => callOrder++.Should().Be(1));
            unitOfWork.Setup(d => d.Commit()).Callback(() => callOrder++.Should().Be(2));

            // Act

            decorator.Handle(command);
        }
        public void Handle_WithoutTransactionalAttributeAndNotGloballyEnabled_ShouldNotCommit(
            [Frozen] Mock<ICommandHandler<ICommand>> commandHandler,
            [Frozen] Mock<IUnitOfWork> unitOfWork,
            [Frozen] Mock<ILogger> logger,
            [Frozen] Mock<IAttributeFinder> attributeFinder,
            [Frozen] GlobalSettings settings,
            ICommand command,
            CommandTransactionDecorator<ICommand> decorator)
        {
            // Arrange

            settings.EnableTransactions = false;

            // Act

            decorator.Handle(command);

            // Assert

            commandHandler.Verify(c => c.Handle(command), Times.Once);

            unitOfWork.Verify(u => u.Clear(), Times.Never);

            unitOfWork.Verify(u => u.Commit(), Times.Never);

            logger.Verify(l => l.Log(It.IsAny<string>()), Times.Never);
        }
        public void Handle_WithoutLogAttributeAndGloballyEnabled_ShouldLog(
            [Frozen] Mock<ICommandHandler<ICommand>> commandHandler,
            [Frozen] Mock<IUnitOfWork> unitOfWork,
            [Frozen] Mock<ILogger> logger,
            [Frozen] Mock<IAttributeFinder> attributeFinder,
            [Frozen] GlobalSettings settings,
            ICommand command,
            CommandTransactionDecorator<ICommand> decorator)
        {
            // Arrange and assert

            settings.EnableLogging = true;

            attributeFinder.Setup(f => f.Decorates(command.GetType(), typeof(TransactionalAttribute))).Returns(true);

            var callOrder = 0;

            unitOfWork.Setup(d => d.Clear()).Callback(() => callOrder++.Should().Be(0));
            commandHandler.Setup(d => d.Handle(command)).Callback(() => callOrder++.Should().Be(1));
            unitOfWork.Setup(d => d.Commit()).Callback(() => callOrder++.Should().Be(2));

            // Act

            decorator.Handle(command);

            // Assert

            logger.Verify(l => l.Log(It.IsAny<string>()), Times.Exactly(2));
        }