Azure Pipeline集成测试无限挂起(疑似LocalDb问题?)
问题背景
用于集成测试的Azure Pipeline两周前可正常运行,上周执行时出现无提示无限挂起,本地环境所有测试运行正常。
已尝试的排查手段
- 将代码及
pipeline.yml回滚至上次正常运行的提交版本 - 在测试启动前配置LocalDB
- 通过独立yml任务从MSI安装SQL Express版本
- 使用包含
Enter-VsDevShell的PowerShell脚本运行测试 sqllocaldb info/stop/delete/start命令返回版本与本地机器一致- 修改连接字符串(脱离mssqllocaldb)后出现其他错误
- 改用
windows-2019代理池而非windows-latest - 采用Debug构建配置进行构建与测试
- 测试任务设置
publishRunAttachments: false - 添加
--blame-hang参数(否则会无限运行) - 为
dotnet test命令添加-p:ParallelizeTestCollections=false参数 - 添加
console;verbosity=detailed参数但未获取有效额外信息 - 连接字符串使用
Server=(localdb)\mssqllocaldb sqlcmd -l 60 -S "(localdb)\mssqllocaldb" -Q "SELECT @@VERSION;"可正常执行
相关配置
连接字符串
{ "ConnectionStrings": { "StorageDbConnection": "Server=(localdb)\\mssqllocaldb;Database=StorageTestDb;Trusted_Connection=True;MultipleActiveResultSets=true", } }
测试项目包引用
<ItemGroup> <PackageReference Include="FluentAssertions" Version="6.10.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" /> <PackageReference Include="Moq" Version="4.18.4" /> <PackageReference Include="Respawn" Version="6.0.0" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="coverlet.collector" Version="3.2.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> </ItemGroup>
流水线测试任务
- task: DotNetCoreCLI@2 name: dotnetTest displayName: Running tests inputs: command: 'test' projects: '**/*Tests/*.csproj' arguments: '--no-build --configuration $(buildConfiguration) --logger "console;verbosity=detailed" --blame-hang --blame-hang-timeout 1min' publishTestResults: false
超时后堆栈跟踪
The active test run was aborted. Reason: Test host process crashed Data collector 'Blame' message: The specified inactivity time of 2 minutes has elapsed. Collecting hang dumps from testhost and its child processes. Data collector 'Blame' message: Dumping 644 - testhost. Attachments: D:\a\1\s\src\Storage\tests\Storage.Application.IntegrationTests\TestResults\7360506b-d062-4e10-8d30-8302c4b56dbd\testhost_644_20230707T081918_hangdump.dmp D:\a\1\s\src\Storage\tests\Storage.Application.IntegrationTests\TestResults\7360506b-d062-4e10-8d30-8302c4b56dbd\Sequence_fd411c6d094d49478d7ee506dc44ebfd.xml Test Run Aborted with error System.Exception: One or more errors occurred. ---> System.Exception: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.. ---> System.Exception: An existing connection was forcibly closed by the remote host. at System.Net.Sockets.NetworkStream.Read(Span`1 buffer) --- End of inner exception stack trace --- at System.Net.Sockets.NetworkStream.Read(Span`1 buffer) at System.Net.Sockets.NetworkStream.ReadByte() at System.IO.BinaryReader.Read7BitEncodedInt() at System.IO.BinaryReader.ReadString() at Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.LengthPrefixCommunicationChannel.NotifyDataAvailable() at Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TcpClientExtensions.MessageLoopAsync(TcpClient client, ICommunicationChannel channel, Action`1 errorHandler, CancellationToken cancellationToken) --- End of inner exception stack trace ---. The active Test Run was aborted because the host process exited unexpectedly. Please inspect the call stack above, if available, to get more information about where the exception originated from.
解答
关于流水线防火墙或权限设置
Azure Pipeline托管代理(如windows-2019/windows-latest)的防火墙规则由微软维护,用户无法直接修改或自定义。LocalDB是本地进程内数据库,无需跨网络通信,因此防火墙不是问题根源。
权限方面,托管代理运行账户已具备LocalDB操作的基础权限,可尝试以下调整:
- 在测试任务前添加PowerShell任务,显式为当前用户创建LocalDB实例:
sqllocaldb create "mssqllocaldb" -s - 确保测试代码中数据库初始化使用
Trusted_Connection=True,避免SQL认证带来的权限问题。
更优调试方法定位超时原因
分析Hang Dump文件
从Pipeline运行详情的"Attachments"下载生成的testhost_xxx_hangdump.dmp文件,用Visual Studio或WinDbg打开:- 加载.NET调试符号,查看调用堆栈定位挂起时的具体代码
- 检查线程状态,排查是否存在死锁、资源等待(如数据库锁、文件锁)
添加测试级详细日志
在集成测试关键步骤(数据库初始化、数据操作、Respawn重置)中添加Console.WriteLine或日志框架输出:- 在测试方法的开始/结束、数据库操作前后打印日志
- 保留
--logger "console;verbosity=detailed"参数确保日志被捕获
隔离单个测试运行
修改dotnet test命令指定单个测试类/方法运行,排查是否由特定测试触发挂起:dotnet test --no-build --configuration Debug --filter "FullyQualifiedName=Namespace.TestClass.TestMethod" --blame-hang --blame-hang-timeout 1min逐步扩大测试范围,定位问题测试用例
临时禁用Respawn
当前使用Respawn重置数据库,尝试临时禁用Respawn改用手动清理数据,排查是否是Respawn在托管环境中出现死锁或超时升级NuGet包版本
测试项目中的Microsoft.NET.Test.Sdk(17.5.0)、xunit.runner.visualstudio(2.4.5)版本较旧,升级到最新稳定版,可能修复托管环境兼容性问题生成测试平台诊断日志
在dotnet test命令中添加--diag:test_diag.log参数,生成测试平台详细诊断日志,日志包含测试进程启动、通信、执行细节:arguments: '--no-build --configuration $(buildConfiguration) --logger "console;verbosity=detailed" --blame-hang --blame-hang-timeout 1min --diag:test_diag.log'下载日志分析异常信息
使用自托管代理测试
若条件允许,用本地机器作为自托管代理运行流水线,对比托管代理环境差异,排查是否是托管环境特定配置导致问题
内容的提问来源于stack exchange,提问作者Allman

