A:初版
This commit is contained in:
1 parent
237cbd8788
commit
ab3721912d
102 files changed
+7929
-20
No files matched your search
@@ -0,0 +1,97 @@
|
||||
using Sharp.NetServer.Middleware;
|
||||
|
||||
namespace NetServer.Test.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// 中间件管道测试(简化版)
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class MiddlewarePipelineTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Pipeline_ShouldExecuteMiddlewaresInOrder()
|
||||
{
|
||||
// Arrange
|
||||
var pipeline = new MiddlewarePipeline();
|
||||
var executionOrder = new List<string>();
|
||||
|
||||
pipeline.Use(next => async context =>
|
||||
{
|
||||
executionOrder.Add("First-Before");
|
||||
await next(context);
|
||||
executionOrder.Add("First-After");
|
||||
});
|
||||
|
||||
pipeline.Use(next => async context =>
|
||||
{
|
||||
executionOrder.Add("Second-Before");
|
||||
await next(context);
|
||||
executionOrder.Add("Second-After");
|
||||
});
|
||||
|
||||
pipeline.Use(next => async context =>
|
||||
{
|
||||
executionOrder.Add("Third");
|
||||
});
|
||||
|
||||
// Act
|
||||
await pipeline.ExecuteAsync(null!); // 简化测试,不需要真实 context
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(5, executionOrder.Count);
|
||||
Assert.AreEqual("First-Before", executionOrder[0]);
|
||||
Assert.AreEqual("Second-Before", executionOrder[1]);
|
||||
Assert.AreEqual("Third", executionOrder[2]);
|
||||
Assert.AreEqual("Second-After", executionOrder[3]);
|
||||
Assert.AreEqual("First-After", executionOrder[4]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Pipeline_ShouldSupportMultipleMiddlewares()
|
||||
{
|
||||
// Arrange
|
||||
var pipeline = new MiddlewarePipeline();
|
||||
var counter = 0;
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
pipeline.Use(next => async context =>
|
||||
{
|
||||
counter++;
|
||||
await next(context);
|
||||
});
|
||||
}
|
||||
|
||||
// Act
|
||||
await pipeline.ExecuteAsync(null!);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(5, counter);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Pipeline_CanShortCircuit()
|
||||
{
|
||||
// Arrange
|
||||
var pipeline = new MiddlewarePipeline();
|
||||
var reachedEnd = false;
|
||||
|
||||
pipeline.Use(next => async context =>
|
||||
{
|
||||
// 短路,不调用 next
|
||||
await Task.CompletedTask;
|
||||
});
|
||||
|
||||
pipeline.Use(next => async context =>
|
||||
{
|
||||
reachedEnd = true;
|
||||
await next(context);
|
||||
});
|
||||
|
||||
// Act
|
||||
await pipeline.ExecuteAsync(null!);
|
||||
|
||||
// Assert
|
||||
Assert.IsFalse(reachedEnd, "Pipeline should be short-circuited");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
using Sharp.NetServer.Routing;
|
||||
using Sharp.NetServer.Attributes;
|
||||
using Sharp.NetServer.Controllers;
|
||||
using Sharp.NetServer.Models;
|
||||
|
||||
namespace NetServer.Test.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// 路由系统测试
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class RouteTableTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void RegisterController_ShouldDiscoverRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new RouteTable();
|
||||
|
||||
// Act
|
||||
routeTable.RegisterController(typeof(TestController));
|
||||
var routes = routeTable.GetAllRoutes();
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(routes);
|
||||
Assert.IsTrue(routes.Count > 0);
|
||||
Assert.IsTrue(routes.Any(r => r.Template == "/api/test/hello"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FindRoute_ShouldMatchCorrectRoute()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new RouteTable();
|
||||
routeTable.RegisterController(typeof(TestController));
|
||||
|
||||
// Act
|
||||
var route = routeTable.FindRoute("GET", "/api/test/hello");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(route);
|
||||
Assert.AreEqual("GET", route.HttpMethod);
|
||||
Assert.AreEqual("/api/test/hello", route.Template);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FindRoute_WithParameter_ShouldMatch()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new RouteTable();
|
||||
routeTable.RegisterController(typeof(TestController));
|
||||
|
||||
// Act
|
||||
var route = routeTable.FindRoute("GET", "/api/test/user/123");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(route);
|
||||
Assert.AreEqual("GET", route.HttpMethod);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FindRoute_InvalidPath_ShouldReturnNull()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new RouteTable();
|
||||
routeTable.RegisterController(typeof(TestController));
|
||||
|
||||
// Act
|
||||
var route = routeTable.FindRoute("GET", "/invalid/path");
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(route);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RegisterController_ShouldCaptureAuthorization()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new RouteTable();
|
||||
|
||||
// Act
|
||||
routeTable.RegisterController(typeof(TestController));
|
||||
var route = routeTable.FindRoute("GET", "/api/test/protected");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(route);
|
||||
Assert.IsTrue(route.RequireAuthorization);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RegisterController_ShouldCaptureAllowAnonymous()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new RouteTable();
|
||||
|
||||
// Act
|
||||
routeTable.RegisterController(typeof(TestController));
|
||||
var route = routeTable.FindRoute("GET", "/api/test/hello");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(route);
|
||||
Assert.IsTrue(route.AllowAnonymous);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RegisterController_ShouldCaptureRateLimit()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new RouteTable();
|
||||
|
||||
// Act
|
||||
routeTable.RegisterController(typeof(TestController));
|
||||
var route = routeTable.FindRoute("GET", "/api/test/limited");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(route);
|
||||
Assert.IsNotNull(route.RateLimitConfig);
|
||||
Assert.AreEqual(100, route.RateLimitConfig.MaxRequests);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用控制器
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/test")]
|
||||
internal class TestController : BaseController
|
||||
{
|
||||
[AllowAnonymous]
|
||||
[HttpGet("hello")]
|
||||
public async Task HelloAsync(HttpContext context)
|
||||
{
|
||||
await WriteSuccessResponseAsync(context, new { message = "Hello" });
|
||||
}
|
||||
|
||||
[HttpGet("user/{id}")]
|
||||
public async Task GetUserAsync(HttpContext context)
|
||||
{
|
||||
await WriteSuccessResponseAsync(context, new { id = "123" });
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpGet("protected")]
|
||||
public async Task ProtectedAsync(HttpContext context)
|
||||
{
|
||||
await WriteSuccessResponseAsync(context, new { message = "Protected" });
|
||||
}
|
||||
|
||||
[RateLimit(100, RateLimitScope.Ip)]
|
||||
[HttpGet("limited")]
|
||||
public async Task LimitedAsync(HttpContext context)
|
||||
{
|
||||
await WriteSuccessResponseAsync(context, new { message = "Limited" });
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user