Azure DevOps流水线中Cosmos Db模拟器单元测试连接失败如何解决
核心问题说明
- 你本地开发环境提前启动了Cosmos DB模拟器,但Azure DevOps流水线的代理节点默认没有运行Cosmos DB模拟器服务,端口8081根本没有服务监听,所以直接报连接被拒绝
- 你当前代码的异步初始化逻辑存在缺陷:构造函数中直接调用
ReadConfigAsync()没有等待执行完成,属于“即发即弃”的调用,就算模拟器已经启动,也很可能出现测试执行时数据库初始化还没完成的情况,本地环境因为执行速度快刚好能跑通,流水线环境性能波动大就会触发报错 - 你当前用的
Direct+Tcp连接模式在流水线代理的网络限制下兼容性较差,也可能加重连接失败的概率
修复步骤
1. 调整Azure DevOps流水线配置
首先确保你的流水线使用Windows操作系统的代理节点(Cosmos DB模拟器仅支持Windows环境),如果是微软托管代理选windows-latest镜像即可,在执行测试任务前新增一个PowerShell任务,预启动Cosmos DB模拟器:
# 启动Cosmos DB模拟器,等待初始化完成 Import-Module "C:\Program Files\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" Start-CosmosDbEmulator -NoUI -Timeout 600
2. 修复代码中的异步初始化问题
将CosmosDataFixture改为实现xUnit的IAsyncLifetime接口来处理异步初始化逻辑,不要在构造函数中调用异步方法:
public class CosmosDataFixture : IDisposable, IAsyncLifetime { public static readonly string CosmosEndpoint = "https://localhost:8081"; public static readonly string EmulatorKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; public static readonly string DatabaseId = "testdb"; public static readonly string RecordingCollection = "testcolec"; public static string Root = Directory.GetParent( Directory.GetCurrentDirectory() ).Parent.Parent.FullName; public static DocumentClient client { get; set; } public async Task InitializeAsync() { // 本地调试可以保留这个方法调用,流水线已经提前启动模拟器可注释减少耗时 // StartEmulatorDatabaseFromPowerShell(); client = new DocumentClient( new Uri( CosmosEndpoint ), EmulatorKey, new ConnectionPolicy { // 流水线环境优先用Gateway模式兼容性更好 ConnectionMode = ConnectionMode.Gateway, ConnectionProtocol = Protocol.Https } ); await client.CreateDatabaseIfNotExistsAsync( new Database { Id = DatabaseId } ); await client.CreateDocumentCollectionIfNotExistsAsync( UriFactory.CreateDatabaseUri( DatabaseId ), new DocumentCollection { Id = RecordingCollection } ); await ReadAllData( client ); } public Task DisposeAsync() { Dispose(); return Task.CompletedTask; } public CosmosDataFixture() { // 异步初始化逻辑移到InitializeAsync中 } public void Dispose() { DeleteDatabaseFromPowerShell(); } } public class CosmosDataTests : IClassFixture<CosmosDataFixture> { // 单元测试逻辑保留即可 }
3. 可选优化
如果流水线启动模拟器还是超时,可以在启动模拟器的PowerShell任务中增加端口预热检测,确认8081端口正常监听后再执行后续测试任务。
内容的提问来源于stack exchange,提问作者ZZZSharePoint
相关产品推荐
相关产品推荐

