Add unit tests and logging infrastructure for InMemory and RabbitMQ transports
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 RecordingLogger and RecordingLoggerFactory for capturing log entries in tests. - Added unit tests for InMemoryChannel, covering constructor behavior, property assignments, channel communication, and disposal. - Created InMemoryTransportOptionsTests to validate default values and customizable options for InMemory transport. - Developed RabbitMqFrameProtocolTests to ensure correct parsing and property creation for RabbitMQ frames. - Added RabbitMqTransportOptionsTests to verify default settings and customization options for RabbitMQ transport. - Updated project files for testing libraries and dependencies.
This commit is contained in:
@@ -0,0 +1,550 @@
|
||||
using System.Text;
|
||||
using StellaOps.Router.Common.Enums;
|
||||
using StellaOps.Router.Common.Frames;
|
||||
using StellaOps.Router.Common.Models;
|
||||
|
||||
namespace StellaOps.Router.Common.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for <see cref="FrameConverter"/>.
|
||||
/// </summary>
|
||||
public sealed class FrameConverterTests
|
||||
{
|
||||
#region ToFrame (RequestFrame) Tests
|
||||
|
||||
[Fact]
|
||||
public void ToFrame_RequestFrame_ReturnsFrameWithRequestType()
|
||||
{
|
||||
// Arrange
|
||||
var request = CreateTestRequestFrame();
|
||||
|
||||
// Act
|
||||
var frame = FrameConverter.ToFrame(request);
|
||||
|
||||
// Assert
|
||||
frame.Type.Should().Be(FrameType.Request);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToFrame_RequestFrame_SetsCorrelationIdFromRequest()
|
||||
{
|
||||
// Arrange
|
||||
var request = CreateTestRequestFrame(correlationId: "test-correlation-123");
|
||||
|
||||
// Act
|
||||
var frame = FrameConverter.ToFrame(request);
|
||||
|
||||
// Assert
|
||||
frame.CorrelationId.Should().Be("test-correlation-123");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToFrame_RequestFrame_UsesRequestIdWhenCorrelationIdIsNull()
|
||||
{
|
||||
// Arrange
|
||||
var request = new RequestFrame
|
||||
{
|
||||
RequestId = "request-id-456",
|
||||
CorrelationId = null,
|
||||
Method = "GET",
|
||||
Path = "/test"
|
||||
};
|
||||
|
||||
// Act
|
||||
var frame = FrameConverter.ToFrame(request);
|
||||
|
||||
// Assert
|
||||
frame.CorrelationId.Should().Be("request-id-456");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToFrame_RequestFrame_SerializesPayload()
|
||||
{
|
||||
// Arrange
|
||||
var request = CreateTestRequestFrame();
|
||||
|
||||
// Act
|
||||
var frame = FrameConverter.ToFrame(request);
|
||||
|
||||
// Assert
|
||||
frame.Payload.Length.Should().BeGreaterThan(0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToRequestFrame Tests
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_ValidRequestFrame_ReturnsRequestFrame()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = CreateTestRequestFrame();
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_WrongFrameType_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var frame = new Frame
|
||||
{
|
||||
Type = FrameType.Response,
|
||||
CorrelationId = "test",
|
||||
Payload = Array.Empty<byte>()
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_InvalidJson_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var frame = new Frame
|
||||
{
|
||||
Type = FrameType.Request,
|
||||
CorrelationId = "test",
|
||||
Payload = Encoding.UTF8.GetBytes("invalid json {{{")
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_RoundTrip_PreservesRequestId()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = CreateTestRequestFrame(requestId: "unique-request-id");
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.RequestId.Should().Be("unique-request-id");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_RoundTrip_PreservesMethod()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = CreateTestRequestFrame(method: "DELETE");
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Method.Should().Be("DELETE");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_RoundTrip_PreservesPath()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = CreateTestRequestFrame(path: "/api/users/123");
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Path.Should().Be("/api/users/123");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_RoundTrip_PreservesHeaders()
|
||||
{
|
||||
// Arrange
|
||||
var headers = new Dictionary<string, string>
|
||||
{
|
||||
["Content-Type"] = "application/json",
|
||||
["X-Custom-Header"] = "custom-value"
|
||||
};
|
||||
var originalRequest = new RequestFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
Method = "POST",
|
||||
Path = "/test",
|
||||
Headers = headers
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Headers.Should().ContainKey("Content-Type");
|
||||
result.Headers["Content-Type"].Should().Be("application/json");
|
||||
result.Headers["X-Custom-Header"].Should().Be("custom-value");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_RoundTrip_PreservesPayload()
|
||||
{
|
||||
// Arrange
|
||||
var payloadBytes = Encoding.UTF8.GetBytes("{\"key\":\"value\"}");
|
||||
var originalRequest = new RequestFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
Method = "POST",
|
||||
Path = "/test",
|
||||
Payload = payloadBytes
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Payload.ToArray().Should().BeEquivalentTo(payloadBytes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_RoundTrip_PreservesTimeoutSeconds()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = new RequestFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
Method = "GET",
|
||||
Path = "/test",
|
||||
TimeoutSeconds = 60
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.TimeoutSeconds.Should().Be(60);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_RoundTrip_PreservesSupportsStreaming()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = new RequestFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
Method = "GET",
|
||||
Path = "/test",
|
||||
SupportsStreaming = true
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.SupportsStreaming.Should().BeTrue();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToFrame (ResponseFrame) Tests
|
||||
|
||||
[Fact]
|
||||
public void ToFrame_ResponseFrame_ReturnsFrameWithResponseType()
|
||||
{
|
||||
// Arrange
|
||||
var response = CreateTestResponseFrame();
|
||||
|
||||
// Act
|
||||
var frame = FrameConverter.ToFrame(response);
|
||||
|
||||
// Assert
|
||||
frame.Type.Should().Be(FrameType.Response);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToFrame_ResponseFrame_SetsCorrelationIdToRequestId()
|
||||
{
|
||||
// Arrange
|
||||
var response = CreateTestResponseFrame(requestId: "req-123");
|
||||
|
||||
// Act
|
||||
var frame = FrameConverter.ToFrame(response);
|
||||
|
||||
// Assert
|
||||
frame.CorrelationId.Should().Be("req-123");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToResponseFrame Tests
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_ValidResponseFrame_ReturnsResponseFrame()
|
||||
{
|
||||
// Arrange
|
||||
var originalResponse = CreateTestResponseFrame();
|
||||
var frame = FrameConverter.ToFrame(originalResponse);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_WrongFrameType_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var frame = new Frame
|
||||
{
|
||||
Type = FrameType.Request,
|
||||
CorrelationId = "test",
|
||||
Payload = Array.Empty<byte>()
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_InvalidJson_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var frame = new Frame
|
||||
{
|
||||
Type = FrameType.Response,
|
||||
CorrelationId = "test",
|
||||
Payload = Encoding.UTF8.GetBytes("not valid json")
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_RoundTrip_PreservesRequestId()
|
||||
{
|
||||
// Arrange
|
||||
var originalResponse = CreateTestResponseFrame(requestId: "original-req-id");
|
||||
var frame = FrameConverter.ToFrame(originalResponse);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.RequestId.Should().Be("original-req-id");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_RoundTrip_PreservesStatusCode()
|
||||
{
|
||||
// Arrange
|
||||
var originalResponse = CreateTestResponseFrame(statusCode: 404);
|
||||
var frame = FrameConverter.ToFrame(originalResponse);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.StatusCode.Should().Be(404);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_RoundTrip_PreservesHeaders()
|
||||
{
|
||||
// Arrange
|
||||
var headers = new Dictionary<string, string>
|
||||
{
|
||||
["Content-Type"] = "application/json",
|
||||
["Cache-Control"] = "no-cache"
|
||||
};
|
||||
var originalResponse = new ResponseFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
StatusCode = 200,
|
||||
Headers = headers
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalResponse);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Headers["Content-Type"].Should().Be("application/json");
|
||||
result.Headers["Cache-Control"].Should().Be("no-cache");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_RoundTrip_PreservesPayload()
|
||||
{
|
||||
// Arrange
|
||||
var payloadBytes = Encoding.UTF8.GetBytes("{\"result\":\"success\"}");
|
||||
var originalResponse = new ResponseFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
StatusCode = 200,
|
||||
Payload = payloadBytes
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalResponse);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Payload.ToArray().Should().BeEquivalentTo(payloadBytes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_RoundTrip_PreservesHasMoreChunks()
|
||||
{
|
||||
// Arrange
|
||||
var originalResponse = new ResponseFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
StatusCode = 200,
|
||||
HasMoreChunks = true
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalResponse);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.HasMoreChunks.Should().BeTrue();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Edge Cases
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_EmptyPayload_ReturnsEmptyPayload()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = new RequestFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
Method = "GET",
|
||||
Path = "/test",
|
||||
Payload = Array.Empty<byte>()
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Payload.IsEmpty.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToRequestFrame_NullHeaders_ReturnsEmptyHeaders()
|
||||
{
|
||||
// Arrange
|
||||
var originalRequest = new RequestFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
Method = "GET",
|
||||
Path = "/test"
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Headers.Should().NotBeNull();
|
||||
result.Headers.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToResponseFrame_EmptyPayload_ReturnsEmptyPayload()
|
||||
{
|
||||
// Arrange
|
||||
var originalResponse = new ResponseFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
StatusCode = 204,
|
||||
Payload = Array.Empty<byte>()
|
||||
};
|
||||
var frame = FrameConverter.ToFrame(originalResponse);
|
||||
|
||||
// Act
|
||||
var result = FrameConverter.ToResponseFrame(frame);
|
||||
|
||||
// Assert
|
||||
result!.Payload.IsEmpty.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToFrame_LargePayload_Succeeds()
|
||||
{
|
||||
// Arrange
|
||||
var largePayload = new byte[1024 * 1024]; // 1MB
|
||||
Random.Shared.NextBytes(largePayload);
|
||||
var originalRequest = new RequestFrame
|
||||
{
|
||||
RequestId = "test-id",
|
||||
Method = "POST",
|
||||
Path = "/upload",
|
||||
Payload = largePayload
|
||||
};
|
||||
|
||||
// Act
|
||||
var frame = FrameConverter.ToFrame(originalRequest);
|
||||
var result = FrameConverter.ToRequestFrame(frame);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
result!.Payload.ToArray().Should().BeEquivalentTo(largePayload);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private static RequestFrame CreateTestRequestFrame(
|
||||
string? requestId = null,
|
||||
string? correlationId = null,
|
||||
string method = "GET",
|
||||
string path = "/test")
|
||||
{
|
||||
return new RequestFrame
|
||||
{
|
||||
RequestId = requestId ?? Guid.NewGuid().ToString("N"),
|
||||
CorrelationId = correlationId,
|
||||
Method = method,
|
||||
Path = path
|
||||
};
|
||||
}
|
||||
|
||||
private static ResponseFrame CreateTestResponseFrame(
|
||||
string? requestId = null,
|
||||
int statusCode = 200)
|
||||
{
|
||||
return new ResponseFrame
|
||||
{
|
||||
RequestId = requestId ?? Guid.NewGuid().ToString("N"),
|
||||
StatusCode = statusCode
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user