public void AddInterceptor_adds_interceptor_for_all_interception_interfaces_implemented()
        {
            var mockInterceptor = new Mock <FakeInterceptor>();

            var dispatchers = new DbDispatchers();

            dispatchers.AddInterceptor(mockInterceptor.Object);

            dispatchers.Command.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Once());

            dispatchers.CommandTree.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(2));

            dispatchers.CancelableCommand.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(3));

            dispatchers.CancelableEntityConnection.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(4));

            dispatchers.Configuration.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(5));

            dispatchers.Connection.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(6));

            dispatchers.Transaction.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(7));
        }
        public void AddInterceptor_adds_interceptor_for_all_interception_interfaces_implemented()
        {
            var mockInterceptor = new Mock<FakeInterceptor>();

            var dispatchers = new DbDispatchers();
            dispatchers.AddInterceptor(mockInterceptor.Object);

            dispatchers.Command.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Once());

            dispatchers.CommandTree.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(2));

            dispatchers.CancelableCommand.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(3));

            dispatchers.CancelableEntityConnection.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(4));

            dispatchers.Configuration.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(5));

            dispatchers.Connection.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(6));

            dispatchers.Transaction.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            mockInterceptor.Verify(m => m.CallMe(), Times.Exactly(7));
        }
        internal CommandTracer(DbContext context, DbDispatchers dispatchers)
        {
            DebugCheck.NotNull(context);
            DebugCheck.NotNull(dispatchers);

            _context = context;
            _dispatchers = dispatchers;

            _dispatchers.AddInterceptor(this);
        }
        public InterceptableDbCommand(DbCommand command, DbInterceptionContext context, DbDispatchers dispatchers = null)
        {
            DebugCheck.NotNull(command);
            DebugCheck.NotNull(context);

            GC.SuppressFinalize(this);

            _command = command;

            _interceptionContext = context;

            _dispatchers = dispatchers ?? DbInterception.Dispatch;
        }
        public void ExecuteScalar_should_dispatch_to_interceptor_and_optionally_execute()
        {
            var mockCommand = new Mock<DbCommand>();
            mockCommand.Setup(m => m.ExecuteScalar()).Returns(11);

            var mockCancelable = new Mock<ICancelableDbCommandInterceptor>();
            var mockPublicInterceptor = new Mock<DbCommandInterceptor> { CallBase = true };

            var dispatchers = new DbDispatchers();
            dispatchers.AddInterceptor(mockCancelable.Object);
            dispatchers.AddInterceptor(mockPublicInterceptor.Object);

            var context = new Mock<InternalContextForMock>().Object.Owner;
            var interceptionContext = new DbInterceptionContext().WithDbContext(context);
            var interceptableDbCommand = new InterceptableDbCommand(mockCommand.Object, interceptionContext, dispatchers);

            mockCancelable.Setup(m => m.CommandExecuting(mockCommand.Object, It.IsAny<DbInterceptionContext>())).Returns(false);

            interceptableDbCommand.ExecuteScalar();

            mockCommand.Verify(m => m.ExecuteScalar(), Times.Never());

            mockCancelable.Verify(m => m.CommandExecuting(mockCommand.Object, interceptionContext), Times.Once());

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuting(It.IsAny<DbCommand>(), It.IsAny<DbCommandInterceptionContext<object>>()), Times.Never());

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuted(It.IsAny<DbCommand>(), It.IsAny<DbCommandInterceptionContext<object>>()), Times.Never());

            mockCancelable.Setup(m => m.CommandExecuting(mockCommand.Object, It.IsAny<DbInterceptionContext>())).Returns(true);

            Assert.Equal(11, interceptableDbCommand.ExecuteScalar());

            mockCommand.Verify(m => m.ExecuteScalar(), Times.Once());

            mockCancelable.Verify(m => m.CommandExecuting(mockCommand.Object, interceptionContext), Times.Exactly(2));

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuting(
                    mockCommand.Object,
                    It.Is<DbCommandInterceptionContext<object>>(c => c.DbContexts.Contains(context, ReferenceEquals))), Times.Once());

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuted(
                    mockCommand.Object,
                    It.Is<DbCommandInterceptionContext<object>>(
                        c => c.DbContexts.Contains(context, ReferenceEquals) && (int)c.Result == 11)), Times.Once());
        }
        public void RemoveInterceptor_removes_interceptor_for_all_interception_interfaces_implemented()
        {
            var mockInterceptor = new Mock <FakeInterceptor>();

            var dispatchers = new DbDispatchers();

            dispatchers.AddInterceptor(mockInterceptor.Object);
            dispatchers.RemoveInterceptor(mockInterceptor.Object);

            dispatchers.Command.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            dispatchers.CommandTree.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            dispatchers.CancelableCommand.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());
            dispatchers.CancelableEntityConnection.InternalDispatcher.Dispatch(i => ((FakeInterceptor)i).CallMe());

            mockInterceptor.Verify(m => m.CallMe(), Times.Never());
        }
        public void ExecuteReaderAsync_should_dispatch_to_interceptor_and_optionally_execute()
        {
            var result = Task.FromResult(new Mock<DbDataReader>().Object);

            var mockCommand = new Mock<DbCommand>();
            mockCommand.Protected()
                .Setup<Task<DbDataReader>>(
                    "ExecuteDbDataReaderAsync", CommandBehavior.SingleRow, ItExpr.IsAny<CancellationToken>())
                .Returns(result);

            var mockCancelable = new Mock<ICancelableDbCommandInterceptor>();
            var mockPublicInterceptor = new Mock<DbCommandInterceptor> { CallBase = true };

            var dispatchers = new DbDispatchers();
            dispatchers.AddInterceptor(mockCancelable.Object);
            dispatchers.AddInterceptor(mockPublicInterceptor.Object);

            var interceptionContext = new DbInterceptionContext();
            var interceptableDbCommand = new InterceptableDbCommand(mockCommand.Object, interceptionContext, dispatchers);

            mockCancelable.Setup(m => m.CommandExecuting(mockCommand.Object, It.IsAny<DbInterceptionContext>())).Returns(false);

            Assert.NotSame(result, interceptableDbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow));

            mockCommand.Protected().Verify(
                "ExecuteDbDataReaderAsync", Times.Never(), CommandBehavior.SingleRow, ItExpr.IsAny<CancellationToken>());

            mockCancelable.Verify(m => m.CommandExecuting(mockCommand.Object, interceptionContext), Times.Once());

            mockPublicInterceptor.Verify(
                m => m.ReaderExecuting(
                    It.IsAny<DbCommand>(),
                    It.IsAny<DbCommandInterceptionContext<DbDataReader>>()), Times.Never());

            mockPublicInterceptor.Verify(
                m => m.ReaderExecuted(
                    It.IsAny<DbCommand>(),
                    It.IsAny<DbCommandInterceptionContext<DbDataReader>>()), Times.Never());

            mockCancelable.Setup(m => m.CommandExecuting(mockCommand.Object, It.IsAny<DbInterceptionContext>())).Returns(true);

            var interceptResult = interceptableDbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow);
            interceptResult.Wait();
            Assert.Same(result.Result, interceptResult.Result);

            mockCommand.Protected().Verify(
                "ExecuteDbDataReaderAsync", Times.Once(), CommandBehavior.SingleRow, ItExpr.IsAny<CancellationToken>());

            mockCancelable.Verify(m => m.CommandExecuting(mockCommand.Object, interceptionContext), Times.Exactly(2));

            mockPublicInterceptor.Verify(
                m => m.ReaderExecuting(
                    mockCommand.Object,
                    It.Is<DbCommandInterceptionContext<DbDataReader>>(c => c.IsAsync && c.CommandBehavior == CommandBehavior.SingleRow)),
                Times.Once());

            mockPublicInterceptor.Verify(
                m => m.ReaderExecuted(
                    mockCommand.Object,
                    It.Is<DbCommandInterceptionContext<DbDataReader>>(
                        c => c.IsAsync && c.CommandBehavior == CommandBehavior.SingleRow && c.Result == result.Result)), Times.Once());
        }
        public void ExecuteScalarAsync_should_dispatch_to_interceptor_and_optionally_execute()
        {
            var mockCommand = new Mock<DbCommand>();
            var result = Task.FromResult<object>(11);
            mockCommand.Setup(m => m.ExecuteScalarAsync(It.IsAny<CancellationToken>())).Returns(result);

            var mockCancelable = new Mock<ICancelableDbCommandInterceptor>();
            var mockPublicInterceptor = new Mock<DbCommandInterceptor> { CallBase = true };

            var dispatchers = new DbDispatchers();
            dispatchers.AddInterceptor(mockCancelable.Object);
            dispatchers.AddInterceptor(mockPublicInterceptor.Object);

            var interceptionContext = new DbInterceptionContext();
            var interceptableDbCommand = new InterceptableDbCommand(mockCommand.Object, interceptionContext, dispatchers);

            mockCancelable.Setup(m => m.CommandExecuting(mockCommand.Object, It.IsAny<DbInterceptionContext>())).Returns(false);

            interceptableDbCommand.ExecuteScalarAsync();

            mockCommand.Verify(m => m.ExecuteScalarAsync(It.IsAny<CancellationToken>()), Times.Never());

            mockCancelable.Verify(m => m.CommandExecuting(mockCommand.Object, interceptionContext), Times.Once());

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuting(It.IsAny<DbCommand>(), It.IsAny<DbCommandInterceptionContext<object>>()), Times.Never());

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuted(It.IsAny<DbCommand>(), It.IsAny<DbCommandInterceptionContext<object>>()),
                Times.Never());

            mockCancelable.Setup(m => m.CommandExecuting(mockCommand.Object, It.IsAny<DbInterceptionContext>())).Returns(true);

            var interceptResult = interceptableDbCommand.ExecuteScalarAsync();
            interceptResult.Wait();
            Assert.Equal(11, interceptResult.Result);

            mockCommand.Verify(m => m.ExecuteScalarAsync(It.IsAny<CancellationToken>()), Times.Once());

            mockCancelable.Verify(m => m.CommandExecuting(mockCommand.Object, interceptionContext), Times.Exactly(2));

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuting(mockCommand.Object, It.Is<DbCommandInterceptionContext<object>>(c => c.IsAsync)), Times.Once());

            mockPublicInterceptor.Verify(
                m => m.ScalarExecuted(
                    mockCommand.Object, It.Is<DbCommandInterceptionContext<object>>(c => c.IsAsync && (int)c.Result == 11)), Times.Once());
        }