public async Task SendAsync_IfSendAsyncThrows_Controller_CallsExceptionServices()
        {
            // Arrange
            Exception expectedException = CreateException();

            Mock <IExceptionLogger> exceptionLoggerMock = CreateStubExceptionLoggerMock();
            IExceptionLogger        exceptionLogger     = exceptionLoggerMock.Object;

            Mock <IExceptionHandler> exceptionHandlerMock = CreateStubExceptionHandlerMock();
            IExceptionHandler        exceptionHandler     = exceptionHandlerMock.Object;

            var controller = new ThrowingController(expectedException);

            var controllerActivator = new Mock <IHttpControllerActivator>();

            controllerActivator
            .Setup(
                activator => activator.Create(
                    It.IsAny <HttpRequestMessage>(),
                    It.IsAny <HttpControllerDescriptor>(),
                    It.IsAny <Type>()))
            .Returns(controller);

            using (HttpRequestMessage expectedRequest = CreateRequestWithRouteData())
                using (HttpConfiguration configuration = CreateConfiguration())
                    using (HttpMessageHandler product = CreateProductUnderTest(configuration, exceptionLogger,
                                                                               exceptionHandler))
                    {
                        var controllerSelector = new Mock <IHttpControllerSelector>(MockBehavior.Strict);
                        controllerSelector
                        .Setup(selector => selector.SelectController(It.IsAny <HttpRequestMessage>()))
                        .Returns(new HttpControllerDescriptor(configuration, "Throwing", controller.GetType()));

                        configuration.Services.Replace(typeof(IHttpControllerSelector), controllerSelector.Object);
                        configuration.Services.Replace(typeof(IHttpControllerActivator), controllerActivator.Object);

                        CancellationToken cancellationToken = CreateCancellationToken();

                        // Act
                        await Assert.ThrowsAsync <Exception>(() => product.SendAsync(expectedRequest, cancellationToken));

                        // Assert
                        Func <ExceptionContext, bool> exceptionContextMatches = (c) =>
                                                                                c != null &&
                                                                                c.Exception == expectedException &&
                                                                                c.CatchBlock == ExceptionCatchBlocks.HttpControllerDispatcher &&
                                                                                c.Request == expectedRequest &&
                                                                                c.ControllerContext != null &&
                                                                                c.ControllerContext == controller.ControllerContext &&
                                                                                c.ControllerContext.Controller == controller;

                        exceptionLoggerMock.Verify(l => l.LogAsync(
                                                       It.Is <ExceptionLoggerContext>(c => exceptionContextMatches(c.ExceptionContext)),
                                                       cancellationToken), Times.Once());

                        exceptionHandlerMock.Verify(h => h.HandleAsync(
                                                        It.Is <ExceptionHandlerContext>((c) => exceptionContextMatches(c.ExceptionContext)),
                                                        cancellationToken), Times.Once());
                    }
        }
        public void SendAsync_IfSendAsyncThrows_Controller_CallsExceptionServices()
        {
            // Arrange
            Exception expectedException = CreateException();

            Mock<IExceptionLogger> exceptionLoggerMock = CreateStubExceptionLoggerMock();
            IExceptionLogger exceptionLogger = exceptionLoggerMock.Object;

            Mock<IExceptionHandler> exceptionHandlerMock = CreateStubExceptionHandlerMock();
            IExceptionHandler exceptionHandler = exceptionHandlerMock.Object;

            var controller = new ThrowingController(expectedException);

            var controllerActivator = new Mock<IHttpControllerActivator>();
            controllerActivator
                .Setup(
                    activator => activator.Create(
                        It.IsAny<HttpRequestMessage>(), 
                        It.IsAny<HttpControllerDescriptor>(), 
                        It.IsAny<Type>()))
                .Returns(controller);

            using (HttpRequestMessage expectedRequest = CreateRequestWithRouteData())
            using (HttpConfiguration configuration = CreateConfiguration())
            using (HttpMessageHandler product = CreateProductUnderTest(configuration, exceptionLogger,
                exceptionHandler))
            {
                var controllerSelector = new Mock<IHttpControllerSelector>(MockBehavior.Strict);
                controllerSelector
                    .Setup(selector => selector.SelectController(It.IsAny<HttpRequestMessage>()))
                    .Returns(new HttpControllerDescriptor(configuration, "Throwing", controller.GetType()));

                configuration.Services.Replace(typeof(IHttpControllerSelector), controllerSelector.Object);
                configuration.Services.Replace(typeof(IHttpControllerActivator), controllerActivator.Object);

                CancellationToken cancellationToken = CreateCancellationToken();

                Task<HttpResponseMessage> task = product.SendAsync(expectedRequest, cancellationToken);

                // Act
                task.WaitUntilCompleted();

                // Assert
                Func<ExceptionContext, bool> exceptionContextMatches = (c) =>
                    c != null
                    && c.Exception == expectedException
                    && c.CatchBlock == ExceptionCatchBlocks.HttpControllerDispatcher
                    && c.Request == expectedRequest
                    && c.ControllerContext != null
                    && c.ControllerContext == controller.ControllerContext
                    && c.ControllerContext.Controller == controller;

                exceptionLoggerMock.Verify(l => l.LogAsync(
                    It.Is<ExceptionLoggerContext>(c => exceptionContextMatches(c.ExceptionContext)),
                    cancellationToken), Times.Once());

                exceptionHandlerMock.Verify(h => h.HandleAsync(
                    It.Is<ExceptionHandlerContext>((c) => exceptionContextMatches(c.ExceptionContext)),
                    cancellationToken), Times.Once());
            }
        }