IMPL-12: 完善端到端集成测试基础设施和修复递归问题
- 更新 TestFixture 添加 Mock Redis 和内存数据库配置 - 修复 DynamicProxyConfigProvider 中的递归问题 - 添加 GwPendingServiceDiscovery 实体模型 - 修复测试数据模型与实际代码的匹配问题 37/44 集成测试通过,失败测试主要由于测试间状态共享
This commit is contained in:
parent
9b77169b80
commit
faba26043f
@ -32,7 +32,7 @@ public class DynamicProxyConfigProvider : IProxyConfigProvider
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_cts?.Cancel();
|
||||
var oldCts = _cts;
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
var routes = _routeProvider.GetRoutes();
|
||||
@ -44,6 +44,9 @@ public class DynamicProxyConfigProvider : IProxyConfigProvider
|
||||
Array.Empty<IReadOnlyDictionary<string, string>>(),
|
||||
_cts.Token
|
||||
);
|
||||
|
||||
// 在设置新配置后再取消旧的 token,避免递归
|
||||
oldCts?.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Moq;
|
||||
using StackExchange.Redis;
|
||||
using Xunit;
|
||||
using YarpGateway.Data;
|
||||
using YarpGateway.DynamicProxy;
|
||||
@ -27,23 +29,18 @@ public class TestFixture : IAsyncLifetime
|
||||
.WithWebHostBuilder(builder =>
|
||||
{
|
||||
builder.UseEnvironment("Testing");
|
||||
builder.ConfigureServices(services =>
|
||||
builder.ConfigureServices((context, services) =>
|
||||
{
|
||||
// 移除 PostgreSQL 数据库上下文
|
||||
var descriptor = services.SingleOrDefault(
|
||||
d => d.ServiceType == typeof(IDbContextFactory<GatewayDbContext>));
|
||||
if (descriptor != null)
|
||||
// 移除所有与 GatewayDbContext 相关的服务
|
||||
var descriptorsToRemove = services
|
||||
.Where(d => d.ServiceType.Name.Contains("DbContext") ||
|
||||
d.ServiceType.Name.Contains("GatewayDbContext"))
|
||||
.ToList();
|
||||
foreach (var descriptor in descriptorsToRemove)
|
||||
{
|
||||
services.Remove(descriptor);
|
||||
}
|
||||
|
||||
var dbContextDescriptor = services.SingleOrDefault(
|
||||
d => d.ServiceType == typeof(DbContextOptions<GatewayDbContext>));
|
||||
if (dbContextDescriptor != null)
|
||||
{
|
||||
services.Remove(dbContextDescriptor);
|
||||
}
|
||||
|
||||
// 使用内存数据库替换
|
||||
services.AddDbContextFactory<GatewayDbContext>(options =>
|
||||
{
|
||||
@ -63,6 +60,18 @@ public class TestFixture : IAsyncLifetime
|
||||
services.RemoveAll(typeof(StackExchange.Redis.IConnectionMultiplexer));
|
||||
services.RemoveAll(typeof(IRedisConnectionManager));
|
||||
|
||||
// 移除分布式负载均衡策略(需要 Redis)
|
||||
services.RemoveAll(typeof(Yarp.ReverseProxy.LoadBalancing.ILoadBalancingPolicy));
|
||||
|
||||
// 添加 Mock Redis 连接
|
||||
var mockRedis = new Mock<IConnectionMultiplexer>();
|
||||
var mockDb = new Mock<IDatabase>();
|
||||
mockDb.Setup(db => db.StringSet(It.IsAny<RedisKey>(), It.IsAny<RedisValue>(), It.IsAny<TimeSpan?>(), It.IsAny<When>(), It.IsAny<CommandFlags>())).Returns(true);
|
||||
mockDb.Setup(db => db.StringGet(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>())).Returns(RedisValue.Null);
|
||||
mockDb.Setup(db => db.ScriptEvaluate(It.IsAny<string>(), It.IsAny<RedisKey[]>(), It.IsAny<RedisValue[]>(), It.IsAny<CommandFlags>())).Returns(RedisResult.Create(1));
|
||||
mockRedis.Setup(r => r.GetDatabase(It.IsAny<int>(), It.IsAny<object?>())).Returns(mockDb.Object);
|
||||
services.AddSingleton(mockRedis.Object);
|
||||
|
||||
// 添加内存缓存
|
||||
services.AddMemoryCache();
|
||||
|
||||
@ -152,13 +161,11 @@ public class TestFixture : IAsyncLifetime
|
||||
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
// 初始化 RouteCache
|
||||
// 初始化 RouteCache(注意:不要在初始化后调用 UpdateConfig,
|
||||
// 因为 DynamicProxyConfigProvider 构造函数中已经调用了它,
|
||||
// 额外的调用可能导致 YARP 配置管理器的递归问题)
|
||||
var routeCache = scope.ServiceProvider.GetRequiredService<IRouteCache>();
|
||||
await routeCache.InitializeAsync();
|
||||
|
||||
// 初始化配置提供程序
|
||||
var configProvider = scope.ServiceProvider.GetRequiredService<DynamicProxyConfigProvider>();
|
||||
configProvider.UpdateConfig();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user