using System.Net; using System.Net.Sockets; using GmRelay.Bot.Infrastructure.Health; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; namespace GmRelay.Bot.Tests.Infrastructure.Health; public sealed class BotHealthCheckHostedServiceTests : IDisposable { private readonly BotHealthCheckHostedService _service; private readonly int _port; public BotHealthCheckHostedServiceTests() { _port = GetAvailablePort(); var config = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { ["HealthCheck:Prefix"] = $"http://localhost:{_port}/" }) .Build(); _service = new BotHealthCheckHostedService( NullLogger.Instance, config); } public void Dispose() { _service.StopAsync(CancellationToken.None).Wait(TimeSpan.FromSeconds(5)); } [Fact] public async Task HealthEndpoint_ShouldReturn200_WhenServiceIsRunning() { await _service.StartAsync(CancellationToken.None); using var client = new HttpClient(); client.Timeout = TimeSpan.FromSeconds(5); var response = await client.GetAsync($"http://localhost:{_port}/health"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } private static int GetAvailablePort() { var listener = new TcpListener(IPAddress.Loopback, 0); listener.Start(); var port = ((IPEndPoint)listener.LocalEndpoint).Port; listener.Stop(); return port; } }