svrnty-mcp-gateway/tests/Svrnty.MCP.Gateway.Infrastructure.Tests/Health/ActiveHealthCheckerTests.cs
Svrnty 19ef79362e refactor: rename OpenHarbor.MCP to Svrnty.MCP across all libraries
- Renamed all directories: OpenHarbor.MCP.* → Svrnty.MCP.*
- Updated all namespaces in 179 C# files
- Renamed 20 .csproj files and 3 .sln files
- Updated 193 documentation references
- Updated 33 references in main CODEX codebase
- Updated Codex.sln with new paths
- Build verified: 0 errors

Preparing for extraction to standalone repositories.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:04:17 -04:00

311 lines
10 KiB
C#

using Xunit;
using Moq;
using Svrnty.MCP.Gateway.Infrastructure.Health;
using Svrnty.MCP.Gateway.Core.Interfaces;
using Svrnty.MCP.Gateway.Core.Models;
namespace Svrnty.MCP.Gateway.Infrastructure.Tests.Health;
/// <summary>
/// Unit tests for ActiveHealthChecker following TDD approach.
/// Tests periodic health checks with configurable intervals.
/// </summary>
public class ActiveHealthCheckerTests
{
[Fact]
public async Task CheckHealthAsync_WithHealthyServer_ReturnsHealthyStatus()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var mockConnection = new Mock<IServerConnection>();
mockConnection.Setup(c => c.IsConnected).Returns(true);
mockConnection.Setup(c => c.ServerInfo).Returns(new ServerInfo
{
Id = "server-1",
Name = "Test Server",
IsHealthy = true,
ResponseTime = TimeSpan.FromMilliseconds(50)
});
mockPool.Setup(p => p.GetConnectionAsync(It.IsAny<ServerConfig>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(mockConnection.Object);
var checker = new ActiveHealthChecker(mockPool.Object);
var serverConfig = new ServerConfig
{
Id = "server-1",
Name = "Test Server",
TransportType = "Http",
BaseUrl = "http://localhost:5000"
};
// Act
var result = await checker.CheckHealthAsync(serverConfig);
// Assert
Assert.NotNull(result);
Assert.Equal("server-1", result.ServerId);
Assert.Equal("Test Server", result.ServerName);
Assert.True(result.IsHealthy);
Assert.NotNull(result.ResponseTime);
}
[Fact]
public async Task CheckHealthAsync_WithUnhealthyServer_ReturnsUnhealthyStatus()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var mockConnection = new Mock<IServerConnection>();
mockConnection.Setup(c => c.IsConnected).Returns(false);
mockConnection.Setup(c => c.ServerInfo).Returns(new ServerInfo
{
Id = "server-2",
Name = "Unhealthy Server",
IsHealthy = false
});
mockPool.Setup(p => p.GetConnectionAsync(It.IsAny<ServerConfig>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(mockConnection.Object);
var checker = new ActiveHealthChecker(mockPool.Object);
var serverConfig = new ServerConfig
{
Id = "server-2",
Name = "Unhealthy Server",
TransportType = "Http",
BaseUrl = "http://localhost:5001"
};
// Act
var result = await checker.CheckHealthAsync(serverConfig);
// Assert
Assert.NotNull(result);
Assert.Equal("server-2", result.ServerId);
Assert.False(result.IsHealthy);
}
[Fact]
public async Task CheckHealthAsync_WithConnectionException_ReturnsUnhealthyStatus()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
mockPool.Setup(p => p.GetConnectionAsync(It.IsAny<ServerConfig>(), It.IsAny<CancellationToken>()))
.ThrowsAsync(new Exception("Connection failed"));
var checker = new ActiveHealthChecker(mockPool.Object);
var serverConfig = new ServerConfig
{
Id = "server-3",
Name = "Failed Server",
TransportType = "Http",
BaseUrl = "http://localhost:5002"
};
// Act
var result = await checker.CheckHealthAsync(serverConfig);
// Assert
Assert.NotNull(result);
Assert.Equal("server-3", result.ServerId);
Assert.False(result.IsHealthy);
Assert.Contains("Connection failed", result.ErrorMessage);
}
[Fact]
public async Task StartMonitoringAsync_BeginsPeriodicChecks()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var mockConnection = new Mock<IServerConnection>();
mockConnection.Setup(c => c.IsConnected).Returns(true);
mockConnection.Setup(c => c.ServerInfo).Returns(new ServerInfo
{
Id = "server-1",
Name = "Test Server",
IsHealthy = true
});
mockPool.Setup(p => p.GetConnectionAsync(It.IsAny<ServerConfig>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(mockConnection.Object);
var checker = new ActiveHealthChecker(mockPool.Object)
{
CheckInterval = TimeSpan.FromMilliseconds(100) // Fast interval for testing
};
var serverConfigs = new List<ServerConfig>
{
new ServerConfig { Id = "server-1", Name = "Test Server", TransportType = "Http", BaseUrl = "http://localhost:5000" }
};
// Act
await checker.StartMonitoringAsync(serverConfigs);
await Task.Delay(50); // Allow initial check to start
// Assert - monitoring should be active
var health = await checker.GetCurrentHealthAsync();
Assert.NotNull(health);
Assert.Contains(health, s => s.ServerId == "server-1");
}
[Fact]
public async Task StopMonitoringAsync_EndsPeriodicChecks()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var checker = new ActiveHealthChecker(mockPool.Object);
var serverConfigs = new List<ServerConfig>
{
new ServerConfig { Id = "server-1", Name = "Test Server", TransportType = "Http", BaseUrl = "http://localhost:5000" }
};
await checker.StartMonitoringAsync(serverConfigs);
// Act
await checker.StopMonitoringAsync();
// Assert - should complete without error
Assert.True(true);
}
[Fact]
public async Task GetCurrentHealthAsync_ReturnsLatestHealthStatus()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var mockConnection = new Mock<IServerConnection>();
mockConnection.Setup(c => c.IsConnected).Returns(true);
mockConnection.Setup(c => c.ServerInfo).Returns(new ServerInfo
{
Id = "server-1",
Name = "Test Server",
IsHealthy = true
});
mockPool.Setup(p => p.GetConnectionAsync(It.IsAny<ServerConfig>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(mockConnection.Object);
var checker = new ActiveHealthChecker(mockPool.Object);
var serverConfig = new ServerConfig
{
Id = "server-1",
Name = "Test Server",
TransportType = "Http",
BaseUrl = "http://localhost:5000"
};
// Perform a check to populate status
await checker.CheckHealthAsync(serverConfig);
// Act
var health = await checker.GetCurrentHealthAsync();
// Assert
Assert.NotNull(health);
Assert.Single(health);
Assert.Equal("server-1", health.First().ServerId);
Assert.True(health.First().IsHealthy);
}
[Fact]
public async Task StartMonitoringAsync_WithMultipleServers_ChecksAllServers()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var mockConnection1 = new Mock<IServerConnection>();
var mockConnection2 = new Mock<IServerConnection>();
mockConnection1.Setup(c => c.IsConnected).Returns(true);
mockConnection1.Setup(c => c.ServerInfo).Returns(new ServerInfo { Id = "server-1", IsHealthy = true });
mockConnection2.Setup(c => c.IsConnected).Returns(true);
mockConnection2.Setup(c => c.ServerInfo).Returns(new ServerInfo { Id = "server-2", IsHealthy = true });
mockPool.Setup(p => p.GetConnectionAsync(It.Is<ServerConfig>(sc => sc.Id == "server-1"), It.IsAny<CancellationToken>()))
.ReturnsAsync(mockConnection1.Object);
mockPool.Setup(p => p.GetConnectionAsync(It.Is<ServerConfig>(sc => sc.Id == "server-2"), It.IsAny<CancellationToken>()))
.ReturnsAsync(mockConnection2.Object);
var checker = new ActiveHealthChecker(mockPool.Object)
{
CheckInterval = TimeSpan.FromMilliseconds(100)
};
var serverConfigs = new List<ServerConfig>
{
new ServerConfig { Id = "server-1", Name = "Server 1", TransportType = "Http", BaseUrl = "http://localhost:5000" },
new ServerConfig { Id = "server-2", Name = "Server 2", TransportType = "Http", BaseUrl = "http://localhost:5001" }
};
// Act
await checker.StartMonitoringAsync(serverConfigs);
await Task.Delay(50);
// Assert
var health = await checker.GetCurrentHealthAsync();
Assert.Equal(2, health.Count());
Assert.Contains(health, s => s.ServerId == "server-1");
Assert.Contains(health, s => s.ServerId == "server-2");
await checker.StopMonitoringAsync();
}
[Fact]
public void Constructor_WithNullPool_ThrowsArgumentNullException()
{
// Act & Assert
Assert.Throws<ArgumentNullException>(() => new ActiveHealthChecker(null!));
}
[Fact]
public async Task CheckHealthAsync_WithNullConfig_ThrowsArgumentNullException()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var checker = new ActiveHealthChecker(mockPool.Object);
// Act & Assert
await Assert.ThrowsAsync<ArgumentNullException>(() => checker.CheckHealthAsync(null!));
}
[Fact]
public async Task CheckHealthAsync_SetsLastCheckTime()
{
// Arrange
var mockPool = new Mock<IServerConnectionPool>();
var mockConnection = new Mock<IServerConnection>();
var beforeCheck = DateTime.UtcNow;
mockConnection.Setup(c => c.IsConnected).Returns(true);
mockConnection.Setup(c => c.ServerInfo).Returns(new ServerInfo { Id = "server-1", IsHealthy = true });
mockPool.Setup(p => p.GetConnectionAsync(It.IsAny<ServerConfig>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(mockConnection.Object);
var checker = new ActiveHealthChecker(mockPool.Object);
var serverConfig = new ServerConfig
{
Id = "server-1",
Name = "Test Server",
TransportType = "Http",
BaseUrl = "http://localhost:5000"
};
// Act
var result = await checker.CheckHealthAsync(serverConfig);
var afterCheck = DateTime.UtcNow;
// Assert
Assert.True(result.LastCheck >= beforeCheck);
Assert.True(result.LastCheck <= afterCheck);
}
}