svrnty-mcp-gateway/tests/Svrnty.MCP.Gateway.AspNetCore.Tests/Middleware/GatewayMiddlewareTests.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

192 lines
6.9 KiB
C#

using Xunit;
using Moq;
using Microsoft.AspNetCore.Http;
using Svrnty.MCP.Gateway.AspNetCore.Middleware;
using Svrnty.MCP.Gateway.Core.Interfaces;
using Svrnty.MCP.Gateway.Core.Models;
using System.Text;
using System.Text.Json;
namespace Svrnty.MCP.Gateway.AspNetCore.Tests.Middleware;
/// <summary>
/// Unit tests for GatewayMiddleware following TDD approach.
/// Tests HTTP request interception and gateway routing.
/// </summary>
public class GatewayMiddlewareTests
{
[Fact]
public async Task InvokeAsync_WithGatewayRequest_RoutesToGateway()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
mockRouter.Setup(r => r.RouteAsync(It.IsAny<GatewayRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new GatewayResponse { Success = true, Result = new Dictionary<string, object> { ["data"] = "test" } });
var middleware = new GatewayMiddleware(
next: (HttpContext _) => Task.CompletedTask,
router: mockRouter.Object
);
var context = new DefaultHttpContext();
context.Request.Method = "POST";
context.Request.Path = "/mcp/invoke";
context.Request.ContentType = "application/json";
var requestBody = JsonSerializer.Serialize(new { toolName = "test_tool", arguments = new { } });
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(requestBody));
context.Response.Body = new MemoryStream();
// Act
await middleware.InvokeAsync(context);
// Assert
mockRouter.Verify(r => r.RouteAsync(It.Is<GatewayRequest>(req => req.ToolName == "test_tool"), It.IsAny<CancellationToken>()), Times.Once);
Assert.Equal(200, context.Response.StatusCode);
}
[Fact]
public async Task InvokeAsync_WithNonGatewayPath_CallsNext()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var nextCalled = false;
var middleware = new GatewayMiddleware(
next: (HttpContext _) => { nextCalled = true; return Task.CompletedTask; },
router: mockRouter.Object
);
var context = new DefaultHttpContext();
context.Request.Method = "GET";
context.Request.Path = "/api/other";
// Act
await middleware.InvokeAsync(context);
// Assert
Assert.True(nextCalled);
mockRouter.Verify(r => r.RouteAsync(It.IsAny<GatewayRequest>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
public async Task InvokeAsync_WithGatewayError_Returns500()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
mockRouter.Setup(r => r.RouteAsync(It.IsAny<GatewayRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new GatewayResponse { Success = false, Error = "Routing failed", ErrorCode = "ROUTE_ERROR" });
var middleware = new GatewayMiddleware(
next: (HttpContext _) => Task.CompletedTask,
router: mockRouter.Object
);
var context = new DefaultHttpContext();
context.Request.Method = "POST";
context.Request.Path = "/mcp/invoke";
context.Request.ContentType = "application/json";
var requestBody = JsonSerializer.Serialize(new { toolName = "test_tool" });
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(requestBody));
context.Response.Body = new MemoryStream();
// Act
await middleware.InvokeAsync(context);
// Assert
Assert.Equal(500, context.Response.StatusCode);
}
[Fact]
public async Task InvokeAsync_WithInvalidJson_Returns400()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var middleware = new GatewayMiddleware(
next: (HttpContext _) => Task.CompletedTask,
router: mockRouter.Object
);
var context = new DefaultHttpContext();
context.Request.Method = "POST";
context.Request.Path = "/mcp/invoke";
context.Request.ContentType = "application/json";
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("invalid json"));
context.Response.Body = new MemoryStream();
// Act
await middleware.InvokeAsync(context);
// Assert
Assert.Equal(400, context.Response.StatusCode);
}
[Fact]
public async Task InvokeAsync_ExtractsClientIdFromHeader()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
mockRouter.Setup(r => r.RouteAsync(It.IsAny<GatewayRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new GatewayResponse { Success = true });
var middleware = new GatewayMiddleware(
next: (HttpContext _) => Task.CompletedTask,
router: mockRouter.Object
);
var context = new DefaultHttpContext();
context.Request.Method = "POST";
context.Request.Path = "/mcp/invoke";
context.Request.ContentType = "application/json";
context.Request.Headers["X-Client-Id"] = "test-client";
var requestBody = JsonSerializer.Serialize(new { toolName = "test_tool" });
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(requestBody));
context.Response.Body = new MemoryStream();
// Act
await middleware.InvokeAsync(context);
// Assert
mockRouter.Verify(r => r.RouteAsync(
It.Is<GatewayRequest>(req => req.ClientId == "test-client"),
It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task InvokeAsync_ReturnsJsonResponse()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var expectedResult = new Dictionary<string, object> { ["status"] = "success", ["value"] = 42 };
mockRouter.Setup(r => r.RouteAsync(It.IsAny<GatewayRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new GatewayResponse { Success = true, Result = expectedResult });
var middleware = new GatewayMiddleware(
next: (HttpContext _) => Task.CompletedTask,
router: mockRouter.Object
);
var context = new DefaultHttpContext();
context.Request.Method = "POST";
context.Request.Path = "/mcp/invoke";
context.Request.ContentType = "application/json";
var requestBody = JsonSerializer.Serialize(new { toolName = "test_tool" });
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(requestBody));
context.Response.Body = new MemoryStream();
// Act
await middleware.InvokeAsync(context);
// Assert
Assert.Equal("application/json", context.Response.ContentType);
context.Response.Body.Seek(0, SeekOrigin.Begin);
var responseBody = await new StreamReader(context.Response.Body).ReadToEndAsync();
Assert.Contains("success", responseBody);
Assert.Contains("42", responseBody);
}
}