已捕获异常但Pester测试仍失败,是用法问题还是Pester Bug?
Pester测试中已捕获的异常仍导致测试失败?
我编写了一个专门捕获并忽略特定异常的PowerShell工具函数Test-FSPath,但使用Pester进行测试时,测试仍失败并显示已被捕获处理的异常。请问是我遗漏了某些配置,还是Pester存在Bug?
复现代码
function Test-FSPath { [cmdletbinding()] param([string]$FileSystemPath) if([string]::IsNullOrWhiteSpace($FileSystemPath)) { return $false } $result = $false try { if(Test-Path $FileSystemPath) { Write-Debug "Verifying that $FileSystemPath is a file system path" $item = Get-Item $FileSystemPath -ErrorAction Ignore $result = ($item -ne $null) -and $($item.PSProvider.Name -eq 'FileSystem') } } catch { # Path pattern that Test-Path / Get-Item can't handle Write-Debug "Ignoring exception $($_.Exception.Message)" } return ($result -or ([System.IO.Directory]::Exists($FileSystemPath)) -or ([System.IO.File]::Exists($FileSystemPath))) } Describe 'Test' { Context Test-FSPath { It 'returns true for a path not supported by PowerShell Test-Path' { $absPath = "$env:TEMP\temp-file[weird-chars.txt" [System.IO.File]::WriteAllText($absPath, 'Hello world') $result = Test-FSPath $absPath -Debug $result | Should -Be $true Write-Host "`$result = $result" Remove-Item $absPath } } }
预期与实际结果
预期结果:测试通过
实际结果:测试失败,报错信息如下:
[-] returns true for a path not supported by PowerShell Test-Path 2.62s WildcardPatternException: The specified wildcard character pattern is not valid: temp-file[weird-chars.txt ParameterBindingException: Cannot retrieve the dynamic parameters for the cmdlet. The specified wildcard character pattern is not valid: temp-file[weird-chars.txt
问题原因与解决方案
为什么你的try/catch没捕获到异常?
这不是Pester的Bug,问题出在PowerShell的参数绑定阶段:当路径包含[这种通配符字符时,Test-Path和Get-Item默认使用的-Path参数会把路径当作通配符表达式解析,这个解析过程发生在cmdlet执行之前——也就是你的try块还没开始执行的时候。所以这个WildcardPatternException根本没进入到try/catch的范围里,自然无法被捕获。
解决办法:使用-LiteralPath参数
要避免通配符解析,你需要给Test-Path和Get-Item指定-LiteralPath参数,这个参数会把路径当作纯字符串处理,不会解析任何通配符字符。修改后的函数如下:
function Test-FSPath { [cmdletbinding()] param([string]$FileSystemPath) if([string]::IsNullOrWhiteSpace($FileSystemPath)) { return $false } $result = $false try { # 使用-LiteralPath替代默认的-Path if(Test-Path -LiteralPath $FileSystemPath) { Write-Debug "Verifying that $FileSystemPath is a file system path" # 同样给Get-Item加上-LiteralPath $item = Get-Item -LiteralPath $FileSystemPath -ErrorAction Ignore $result = ($item -ne $null) -and ($item.PSProvider.Name -eq 'FileSystem') } } catch { # Path pattern that Test-Path / Get-Item can't handle Write-Debug "Ignoring exception $($_.Exception.Message)" } return ($result -or ([System.IO.Directory]::Exists($FileSystemPath)) -or ([System.IO.File]::Exists($FileSystemPath))) }
补充说明
你之前添加的-ErrorAction Ignore只能处理cmdlet执行过程中抛出的异常,对参数绑定阶段的异常完全无效——因为参数绑定发生在cmdlet启动执行之前。使用-LiteralPath才是解决这类特殊路径问题的根本方案。
修改后重新运行Pester测试,就能正常通过了。
内容的提问来源于stack exchange,提问作者Joshua Honig
相关产品推荐
相关产品推荐

