Add unit tests for RabbitMq and Udp transport servers and clients
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implemented comprehensive unit tests for RabbitMqTransportServer, covering constructor, disposal, connection management, event handlers, and exception handling. - Added configuration tests for RabbitMqTransportServer to validate SSL, durable queues, auto-recovery, and custom virtual host options. - Created unit tests for UdpFrameProtocol, including frame parsing and serialization, header size validation, and round-trip data preservation. - Developed tests for UdpTransportClient, focusing on connection handling, event subscriptions, and exception scenarios. - Established tests for UdpTransportServer, ensuring proper start/stop behavior, connection state management, and event handling. - Included tests for UdpTransportOptions to verify default values and modification capabilities. - Enhanced service registration tests for Udp transport services in the dependency injection container.
This commit is contained in:
@@ -0,0 +1,333 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using StellaOps.Router.Common.Abstractions;
|
||||
using StellaOps.Router.Common.Enums;
|
||||
using StellaOps.Router.Common.Models;
|
||||
|
||||
namespace StellaOps.Microservice.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for <see cref="RouterConnectionManager"/>.
|
||||
/// </summary>
|
||||
public sealed class RouterConnectionManagerTests : IDisposable
|
||||
{
|
||||
private readonly Mock<IEndpointDiscoveryProvider> _discoveryProviderMock;
|
||||
private readonly Mock<IMicroserviceTransport> _transportMock;
|
||||
private readonly StellaMicroserviceOptions _options;
|
||||
|
||||
public RouterConnectionManagerTests()
|
||||
{
|
||||
_discoveryProviderMock = new Mock<IEndpointDiscoveryProvider>();
|
||||
_transportMock = new Mock<IMicroserviceTransport>();
|
||||
_options = new StellaMicroserviceOptions
|
||||
{
|
||||
ServiceName = "test-service",
|
||||
Version = "1.0.0",
|
||||
Region = "test",
|
||||
InstanceId = "test-instance-1",
|
||||
HeartbeatInterval = TimeSpan.FromMilliseconds(50),
|
||||
ReconnectBackoffInitial = TimeSpan.FromMilliseconds(10),
|
||||
ReconnectBackoffMax = TimeSpan.FromMilliseconds(100)
|
||||
};
|
||||
|
||||
_discoveryProviderMock.Setup(d => d.DiscoverEndpoints())
|
||||
.Returns(new List<EndpointDescriptor>());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Cleanup if needed
|
||||
}
|
||||
|
||||
private RouterConnectionManager CreateManager()
|
||||
{
|
||||
return new RouterConnectionManager(
|
||||
Options.Create(_options),
|
||||
_discoveryProviderMock.Object,
|
||||
_transportMock.Object,
|
||||
NullLogger<RouterConnectionManager>.Instance);
|
||||
}
|
||||
|
||||
#region Constructor Tests
|
||||
|
||||
[Fact]
|
||||
public void Constructor_InitializesCorrectly()
|
||||
{
|
||||
// Act
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Assert
|
||||
manager.Connections.Should().BeEmpty();
|
||||
manager.CurrentStatus.Should().Be(InstanceHealthStatus.Healthy);
|
||||
manager.InFlightRequestCount.Should().Be(0);
|
||||
manager.ErrorRate.Should().Be(0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CurrentStatus Tests
|
||||
|
||||
[Fact]
|
||||
public void CurrentStatus_CanBeSet()
|
||||
{
|
||||
// Arrange
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
manager.CurrentStatus = InstanceHealthStatus.Draining;
|
||||
|
||||
// Assert
|
||||
manager.CurrentStatus.Should().Be(InstanceHealthStatus.Draining);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(InstanceHealthStatus.Healthy)]
|
||||
[InlineData(InstanceHealthStatus.Degraded)]
|
||||
[InlineData(InstanceHealthStatus.Draining)]
|
||||
[InlineData(InstanceHealthStatus.Unhealthy)]
|
||||
public void CurrentStatus_AcceptsAllStatusValues(InstanceHealthStatus status)
|
||||
{
|
||||
// Arrange
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
manager.CurrentStatus = status;
|
||||
|
||||
// Assert
|
||||
manager.CurrentStatus.Should().Be(status);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region InFlightRequestCount Tests
|
||||
|
||||
[Fact]
|
||||
public void InFlightRequestCount_CanBeSet()
|
||||
{
|
||||
// Arrange
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
manager.InFlightRequestCount = 42;
|
||||
|
||||
// Assert
|
||||
manager.InFlightRequestCount.Should().Be(42);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ErrorRate Tests
|
||||
|
||||
[Fact]
|
||||
public void ErrorRate_CanBeSet()
|
||||
{
|
||||
// Arrange
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
manager.ErrorRate = 0.25;
|
||||
|
||||
// Assert
|
||||
manager.ErrorRate.Should().Be(0.25);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region StartAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_DiscoversEndpoints()
|
||||
{
|
||||
// Arrange
|
||||
_options.Routers.Add(new RouterEndpointConfig
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 5000,
|
||||
TransportType = TransportType.InMemory
|
||||
});
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
await manager.StartAsync(CancellationToken.None);
|
||||
await Task.Delay(10);
|
||||
await manager.StopAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
_discoveryProviderMock.Verify(d => d.DiscoverEndpoints(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_WithRouters_CreatesConnections()
|
||||
{
|
||||
// Arrange
|
||||
_options.Routers.Add(new RouterEndpointConfig
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 5000,
|
||||
TransportType = TransportType.InMemory
|
||||
});
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
await manager.StartAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
manager.Connections.Should().HaveCount(1);
|
||||
manager.Connections[0].Instance.ServiceName.Should().Be("test-service");
|
||||
|
||||
// Cleanup
|
||||
await manager.StopAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_RegistersEndpointsInConnection()
|
||||
{
|
||||
// Arrange
|
||||
_options.Routers.Add(new RouterEndpointConfig
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 5000,
|
||||
TransportType = TransportType.InMemory
|
||||
});
|
||||
|
||||
var endpoints = new List<EndpointDescriptor>
|
||||
{
|
||||
new() { ServiceName = "test", Version = "1.0", Method = "GET", Path = "/api/users" },
|
||||
new() { ServiceName = "test", Version = "1.0", Method = "POST", Path = "/api/users" }
|
||||
};
|
||||
_discoveryProviderMock.Setup(d => d.DiscoverEndpoints()).Returns(endpoints);
|
||||
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
await manager.StartAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
manager.Connections[0].Endpoints.Should().HaveCount(2);
|
||||
|
||||
// Cleanup
|
||||
await manager.StopAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_AfterDispose_ThrowsObjectDisposedException()
|
||||
{
|
||||
// Arrange
|
||||
var manager = CreateManager();
|
||||
manager.Dispose();
|
||||
|
||||
// Act
|
||||
var action = () => manager.StartAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
await action.Should().ThrowAsync<ObjectDisposedException>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region StopAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task StopAsync_ClearsConnections()
|
||||
{
|
||||
// Arrange
|
||||
_options.Routers.Add(new RouterEndpointConfig
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 5000,
|
||||
TransportType = TransportType.InMemory
|
||||
});
|
||||
using var manager = CreateManager();
|
||||
await manager.StartAsync(CancellationToken.None);
|
||||
|
||||
// Act
|
||||
await manager.StopAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
manager.Connections.Should().BeEmpty();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Heartbeat Tests
|
||||
|
||||
[Fact]
|
||||
public async Task Heartbeat_SendsViaTransport()
|
||||
{
|
||||
// Arrange
|
||||
_options.Routers.Add(new RouterEndpointConfig
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 5000,
|
||||
TransportType = TransportType.InMemory
|
||||
});
|
||||
using var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
await manager.StartAsync(CancellationToken.None);
|
||||
await Task.Delay(150); // Wait for heartbeat to run
|
||||
await manager.StopAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
_transportMock.Verify(
|
||||
t => t.SendHeartbeatAsync(It.IsAny<HeartbeatPayload>(), It.IsAny<CancellationToken>()),
|
||||
Times.AtLeastOnce);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Heartbeat_IncludesCurrentMetrics()
|
||||
{
|
||||
// Arrange
|
||||
_options.Routers.Add(new RouterEndpointConfig
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 5000,
|
||||
TransportType = TransportType.InMemory
|
||||
});
|
||||
using var manager = CreateManager();
|
||||
manager.CurrentStatus = InstanceHealthStatus.Degraded;
|
||||
manager.InFlightRequestCount = 10;
|
||||
manager.ErrorRate = 0.05;
|
||||
|
||||
HeartbeatPayload? capturedHeartbeat = null;
|
||||
_transportMock.Setup(t => t.SendHeartbeatAsync(It.IsAny<HeartbeatPayload>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<HeartbeatPayload, CancellationToken>((h, _) => capturedHeartbeat = h)
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
// Act
|
||||
await manager.StartAsync(CancellationToken.None);
|
||||
await Task.Delay(150); // Wait for heartbeat
|
||||
await manager.StopAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
capturedHeartbeat.Should().NotBeNull();
|
||||
capturedHeartbeat!.Status.Should().Be(InstanceHealthStatus.Degraded);
|
||||
capturedHeartbeat.InFlightRequestCount.Should().Be(10);
|
||||
capturedHeartbeat.ErrorRate.Should().Be(0.05);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dispose Tests
|
||||
|
||||
[Fact]
|
||||
public void Dispose_CanBeCalledMultipleTimes()
|
||||
{
|
||||
// Arrange
|
||||
var manager = CreateManager();
|
||||
|
||||
// Act
|
||||
var action = () =>
|
||||
{
|
||||
manager.Dispose();
|
||||
manager.Dispose();
|
||||
manager.Dispose();
|
||||
};
|
||||
|
||||
// Assert
|
||||
action.Should().NotThrow();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user