public async Task AutoHealthCheckMiddleware_should_avoid_run_with_un_match_url()
        {
            // arrange
            var engine         = new Mock <IHealthChecker>();
            var defaultOptions = new AutoHealthAppBuilderOptions();

            var middleware = new AutoHealthCheckMiddleware(
                async innerHttpContext => { },
                engine.Object,
                defaultOptions);

            var context  = new Mock <HttpContext>();
            var request  = new Mock <HttpRequest>();
            var response = new Mock <HttpResponse>();

            request.Setup(r => r.Method)
            .Returns("GET");     // valid http method

            request.Setup(c => c.Path)
            .Returns(new PathString("/api/notvalidendpoint"));

            context.Setup(c => c.Request)
            .Returns(request.Object);

            context.Setup(c => c.Response)
            .Returns(response.Object);

            // act
            await middleware.Invoke(context.Object);

            // assert
            engine.Verify(c => c.Check(), Times.Never);
        }
        public async Task AutoHealthCheckMiddleware_should_avoid_run_with_invalid_methods(string method)
        {
            // arrange
            var engine         = new Mock <IHealthChecker>();
            var defaultOptions = new AutoHealthAppBuilderOptions();

            var middleware = new AutoHealthCheckMiddleware(
                async innerHttpContext => { },
                engine.Object,
                defaultOptions);

            var context  = new Mock <HttpContext>();
            var request  = new Mock <HttpRequest>();
            var response = new Mock <HttpResponse>();

            request.Setup(r => r.Method)
            .Returns(method);

            context.Setup(c => c.Request)
            .Returns(request.Object);

            context.Setup(c => c.Response)
            .Returns(response.Object);

            // act
            await middleware.Invoke(context.Object);

            // assert
            engine.Verify(c => c.Check(), Times.Never);
        }
        public async Task AutoHealthCheckMiddleware_should_fail_if_engine_return_null()
        {
            // arrange
            var engine         = new Mock <IHealthChecker>();
            var defaultOptions = new AutoHealthAppBuilderOptions();

            var middleware = new AutoHealthCheckMiddleware(
                async innerHttpContext => { },
                engine.Object,
                defaultOptions);

            var context  = new Mock <HttpContext>();
            var request  = new Mock <HttpRequest>();
            var response = new Mock <HttpResponse>();

            request.Setup(r => r.Method)
            .Returns("GET");     // valid http method

            request.Setup(c => c.Path)
            .Returns(new PathString("/api/autoHealthCheck"));     // default endpoint

            context.Setup(c => c.Request)
            .Returns(request.Object);

            context.Setup(c => c.Response)
            .Returns(response.Object);

            // act
            // assert
            await Assert.ThrowsAsync <ArgumentNullException>(async() => await middleware.Invoke(context.Object));
        }
        public async Task AutoHealthCheckMiddleware_should_do_nothing()
        {
            // arrange
            var engine         = new Mock <IHealthChecker>();
            var defaultOptions = new AutoHealthAppBuilderOptions();

            var middleware = new AutoHealthCheckMiddleware(
                async innerHttpContext => { },
                engine.Object,
                defaultOptions);

            // act
            await middleware.Invoke(new DefaultHttpContext());

            // assert
            engine.Verify(c => c.Check(), Times.Never);
        }
        public static IApplicationBuilder UseAutoHealthCheck(
            this IApplicationBuilder app,
            Action <AutoHealthAppBuilderOptions> setupAction = null)
        {
            var contextAccessorType = typeof(IAutoHealthCheckContextAccessor);

            if (!(app.ApplicationServices.GetService(contextAccessorType) is IAutoHealthCheckContextAccessor contextAccessor))
            {
                throw new InvalidOperationException("Please first call UseAutoHealthCheck.");
            }

            var options = new AutoHealthAppBuilderOptions();

            setupAction?.Invoke(options);

            var context = contextAccessor.Context as AutoHealthCheckContext;

            context.AppBuilderOptions = options;

            app.UseMiddleware <AutoHealthCheckMiddleware>(options);
            return(app);
        }
        public async Task AutoHealthCheckMiddleware_should_run_engine()
        {
            // arrange
            var engine         = new Mock <IHealthChecker>();
            var defaultOptions = new AutoHealthAppBuilderOptions();

            var middleware = new AutoHealthCheckMiddleware(
                async innerHttpContext => { },
                engine.Object,
                defaultOptions);

            var context  = new Mock <HttpContext>();
            var request  = new Mock <HttpRequest>();
            var response = new DefaultHttpResponse(new DefaultHttpContext());

            request.Setup(r => r.Method)
            .Returns("GET");     // valid http method

            request.Setup(c => c.Path)
            .Returns(new PathString("/api/autoHealthCheck"));     // default endpoint

            context.Setup(c => c.Request)
            .Returns(request.Object);

            context.Setup(c => c.Response)
            .Returns(response);

            engine.Setup(c => c.Check())
            .Returns(Task.FromResult(new HealthyResponse()));

            // act
            await middleware.Invoke(context.Object);

            // assert
            engine.Verify(c => c.Check(), Times.Once);
        }