public async Task returns_health_check_status_if_url_contains_healthcheck_ping()
        {
            _context.Request.Scheme = "http";
            _context.Request.Method = "GET";
            _context.Request.Path   = "/healthcheck/ping";
            _context.Request.Host   = new HostString("localhost");

            var healthcheckResult = new HealthCheckResult
            {
                AssemblyName = "HealthCheckMiddlewareTests",
                Version      = "1.0",
                Healthy      = true
            };

            _healthCheck.Setup(x => x.CurrentHealthCheckResult).Returns(healthcheckResult);

            var responseBody = string.Empty;

            using (var memStream = new MemoryStream())
            {
                _context.Response.Body = memStream;

                await _middleware.Invoke(_context);

                memStream.Position = 0;
                responseBody       = new StreamReader(memStream).ReadToEnd();
            }

            Assert.NotNull(_context.Response);
            Assert.Equal(_context.Response.StatusCode, (int)HttpStatusCode.OK);
            Assert.Equal(responseBody, JsonConvert.SerializeObject(healthcheckResult));
        }
        private async void ShouldReturnStatus500WithDetailsEvenIfOneServiceIsUnhealthy()
        {
            var sampleServiceData = new Dictionary <string, string>()
            {
                { "Service1", "Unhealthy" }, { "Service2", "Healthy" }
            };
            var context = new DefaultHttpContext();

            context.Response.Body = new MemoryStream();
            healthCheckClient     = new Mock <IHealthCheckClient>();
            healthCheckClient.Setup(x => x.CheckHealth())
            .Returns(Task.FromResult(sampleServiceData));
            var expectedResult = JsonConvert.SerializeObject(sampleServiceData);

            Dictionary <string, string> unhealthyresponse = new Dictionary <string, string> {
                { "Service1", "Unhealthy" }, { "Service2", "Healthy" }
            };

            healthCheckStatus.Setup(x => x.GetStatus("health"))
            .Returns(unhealthyresponse);

            await healthCheckMiddleWare.Invoke(context);

            context.Response.Body.Seek(0, SeekOrigin.Begin);
            var responseBody = new StreamReader(context.Response.Body).ReadToEnd();

            responseBody
            .Should()
            .BeEquivalentTo(expectedResult);
            context.Response.StatusCode
            .Should()
            .Be(500);
        }
        public async Task Invoke_WithNonMatchingPath_IgnoresRequest()
        {
            var             contextMock = GetMockContext("/nonmatchingpath");
            RequestDelegate next        = _ =>
            {
                return(Task.FromResult <object>(null));
            };

            var options = new Mock <IOptions <HealthCheckOptions> >();

            options.SetupGet(o => o.Value)
            .Returns(new HealthCheckOptions()
            {
                Path = "/healthcheck"
            });

            var loggerFactory = new LoggerFactory();
            var healthService = new Mock <IHealthCheckService>();

            healthService.Setup(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()))
            .ReturnsAsync(HealthCheckResponse.Empty);

            var defaultPolicy  = new HealthCheckPolicy(new HealthCheckSettingsCollection());
            var policyProvider = new DefaultHealthCheckPolicyProvider(defaultPolicy);

            var authZService = new Mock <IAuthorizationService>();

            var healthCheckMiddleware = new HealthCheckMiddleware(next, options.Object, loggerFactory, healthService.Object, policyProvider, authZService.Object);
            await healthCheckMiddleware.Invoke(contextMock.Object);

            healthService.Verify(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()), Times.Never());
        }
        public async Task Invoke_ServerHealthy_Returns200()
        {
            var             contextMock = GetMockContext("/healthcheck");
            RequestDelegate next        = _ =>
            {
                return(Task.FromResult <object>(null));
            };

            var options = new Mock <IOptions <HealthCheckOptions> >();

            options.SetupGet(o => o.Value)
            .Returns(new HealthCheckOptions()
            {
                Path = "/healthcheck"
            });

            var loggerFactory = new LoggerFactory();
            var healthService = new Mock <IHealthCheckService>();

            healthService.Setup(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()))
            .ReturnsAsync(new HealthCheckResponse(new HealthCheckResult[] { new HealthCheckResult {
                                                                                Status = HealthStatus.Healthy
                                                                            } }));

            var defaultPolicy  = new HealthCheckPolicy(new HealthCheckSettingsCollection());
            var policyProvider = new DefaultHealthCheckPolicyProvider(defaultPolicy);

            var authZService          = new Mock <IAuthorizationService>();
            var healthCheckMiddleware = new HealthCheckMiddleware(next, options.Object, loggerFactory, healthService.Object, policyProvider, authZService.Object);
            await healthCheckMiddleware.Invoke(contextMock.Object);

            healthService.Verify(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()), Times.Once());
            Assert.Equal(StatusCodes.Status200OK, contextMock.Object.Response.StatusCode);
        }
        public async Task ReturnsPongBodyContent()
        {
            // Arrange
            var bodyStream = new MemoryStream();
            var context    = new DefaultHttpContext();

            context.Response.Body = bodyStream;
            context.Request.Path  = "/ping";

            RequestDelegate next       = (ctx) => Task.CompletedTask;
            var             middleware = new HealthCheckMiddleware(next: next);

            // Act
            await middleware.Invoke(context);

            string response;

            bodyStream.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(bodyStream))
            {
                response = await reader.ReadToEndAsync();
            }

            // Assert
            response.ShouldBe("pong");
            context.Response.ContentType.ShouldBe("text/plain");
            context.Response.StatusCode.ShouldBe(200);
        }
        public async Task ShouldRespondWith503StatusCodeWithFailureJsonString()
        {
            //Arrange
            var next = GetRequestDelegate();

            var httpContext = new DefaultHttpContext();

            httpContext.Response.Body = new MemoryStream();

            var options = new HealthCheckOptions()
            {
                Path = "/healthcheck"
            };

            httpContext.Request.Path = "/healthcheck";

            var healthCheckMiddleware = new HealthCheckMiddleware(next, _failingHealthChecker, options);

            //Act
            await healthCheckMiddleware.Invoke(httpContext);

            //Assert
            httpContext.Response.StatusCode.ShouldBe(503);
            Assert.IsTrue(ReadBodyAsString(httpContext).Contains("FailingHealthCheck"));
        }
        public async Task ShouldRespondWith200StatusCodeWithSuccessJsonString()
        {
            //Arrange
            var next = GetRequestDelegate();

            var httpContext = new DefaultHttpContext();

            httpContext.Response.Body = new MemoryStream();

            var options = new HealthCheckOptions()
            {
                Path = "/healthcheck"
            };

            httpContext.Request.Path = "/healthcheck";

            var healthCheckMiddleware = new HealthCheckMiddleware(next, _healthChecker, options);

            //Act
            await healthCheckMiddleware.Invoke(httpContext);

            //Assert
            httpContext.Response.StatusCode.ShouldBe(200);
            httpContext.Response.ContentType.ShouldBe("text/plain");
            httpContext.Response.Headers["Content-Disposition"].ToString().ShouldBe("inline");
            httpContext.Response.Headers["Cache-Control"].ToString().ShouldBe("no-cache");

            Assert.IsTrue(ReadBodyAsString(httpContext).Contains("Checks whether the application is running. If this check can run then it should pass."));
        }
        public async Task ShouldRespondWith200StatusCode()
        {
            //Arrange
            var next = GetRequestDelegate();

            var httpContext = new DefaultHttpContext();

            var healthCheckMiddleware = new HealthCheckMiddleware(next, _healthChecker, new HealthCheckOptions());

            //Act
            await healthCheckMiddleware.Invoke(httpContext);

            //Assert
            httpContext.Response.StatusCode = 200;
        }
        public async Task Invoke_AuthZPolicyFailed_DelegateToNextMiddleware()
        {
            var             contextMock = GetMockContext("/healthcheck");
            RequestDelegate next        = _ =>
            {
                _.Response.StatusCode = 404;
                return(Task.FromResult <object>(null));
            };

            var options = new Mock <IOptions <HealthCheckOptions> >();

            options.SetupGet(o => o.Value)
            .Returns(new HealthCheckOptions()
            {
                Path = "/healthcheck",
                AuthorizationPolicy = new AuthorizationPolicyBuilder().RequireClaim("invalid").Build()
            });

            var loggerFactory = new LoggerFactory();
            var healthService = new Mock <IHealthCheckService>();

            healthService.Setup(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()))
            .ReturnsAsync(new HealthCheckResponse(new HealthCheckResult[] { new HealthCheckResult {
                                                                                Status = HealthStatus.Healthy,
                                                                            } }));

            var defaultPolicy  = new HealthCheckPolicy(new HealthCheckSettingsCollection());
            var policyProvider = new DefaultHealthCheckPolicyProvider(defaultPolicy);

            var authZService = new Mock <IAuthorizationService>();

            authZService
            .Setup(s => s.AuthorizeAsync(It.IsAny <ClaimsPrincipal>(), It.IsAny <object>(), It.IsAny <IEnumerable <IAuthorizationRequirement> >()))
            .ReturnsAsync(false);

            var healthCheckMiddleware = new HealthCheckMiddleware(next, options.Object, loggerFactory, healthService.Object, policyProvider, authZService.Object);
            await healthCheckMiddleware.Invoke(contextMock.Object);

            healthService.Verify(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()), Times.Never());
            Assert.Equal(404, contextMock.Object.Response.StatusCode);
        }
        public async Task ForNonMatchingRequest_CallsNextDelegate()
        {
            // Arrange
            var context = new DefaultHttpContext();

            context.Request.Path = "/somethingelse";

            var             wasExecuted = false;
            RequestDelegate next        = (ctx) =>
            {
                wasExecuted = true;
                return(Task.CompletedTask);
            };

            var middleware = new HealthCheckMiddleware(next: next);

            // Act
            await middleware.Invoke(context);

            // Assert
            wasExecuted.ShouldBe(true);
        }
        public async Task Invoke_WithMatchingPolicy_IgnoresRequest()
        {
            var             contextMock = GetMockContext("/healthcheck/matchingpolicy");
            RequestDelegate next        = _ =>
            {
                return(Task.FromResult <object>(null));
            };

            var options = new Mock <IOptions <HealthCheckOptions> >();

            options.SetupGet(o => o.Value)
            .Returns(new HealthCheckOptions()
            {
                Path = "/healthcheck"
            });

            var loggerFactory = new LoggerFactory();
            var healthService = new Mock <IHealthCheckService>();

            healthService.Setup(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()))
            .ReturnsAsync(HealthCheckResponse.Empty);

            var defaultPolicy = new HealthCheckBuilder(new ServiceCollection())
                                .AddCheck("test", ctx =>
            {
                return(TaskCache.CompletedTask);
            }, tags: new[] { "matchingpolicy" })
                                .Build();
            var policyProvider = new DefaultHealthCheckPolicyProvider(defaultPolicy);

            var authZService          = new Mock <IAuthorizationService>();
            var healthCheckMiddleware = new HealthCheckMiddleware(next, options.Object, loggerFactory, healthService.Object, policyProvider, authZService.Object);
            await healthCheckMiddleware.Invoke(contextMock.Object);

            healthService.Verify(s => s.CheckHealthAsync(It.IsAny <HealthCheckPolicy>()), Times.Once());
        }