为什么我不能在 Pester 中测试 ParameterBindingValidationException?
Why can I not test for ParameterBindingValidationException in Pester?
给定一个对参数进行验证的函数:
function Test-Validation {
[CmdletBinding()]
param (
[Parameter()]
[ValidateScript({
# Add some validation that can throw.
if (-not (Test-Path -Path $_ -PathType Container)) {
throw "OutDir must be a folder path, not a file."
}
return $true
})]
[System.String]
$Folder
)
Process {
$Folder + " is a folder!"
}
}
我们应该能够检查错误类型并将其设置为纠缠测试中的 ExpectedType
。
Test-Validation -Folder C:\Temp\file.txt
Test-Validation : Cannot validate argument on parameter 'Folder'. OutDir must be a folder path, not a file.
At line:1 char:17
+ Test-Validation C:\Temp\file.txt
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Test-Validation], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Test-Validation
$Error[0].Exception.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False True ParameterBindingValidationException System.Management.Automation.ParameterBindingException
但是在Pester中测试时,由于找不到类型,测试失败。
$ShouldParams = @{
Throw = $true
ExpectedMessage = "Cannot validate argument on parameter 'OutDir'. OutDir must be a folder path, not a file."
ExceptionType = ([System.Management.Automation.ParameterBindingValidationException])
}
{ Test-Validation -Folder C:\Temp\file.txt } | Should @ShouldParams
# Result
RuntimeException: Unable to find type [System.Management.Automation.ParameterBindingValidationException].
我怎样才能修复这个测试,以便我知道我不仅仅是在捕获任何异常类型?
无法捕获此类型的原因是因为它不是 [System.Management.Automation]
中的 public class。相反,您可以将 -ExceptionType
设置为它派生自 [System.Management.Automation.ParameterBindingException]
的 class,您的测试现在将通过对抛出的异常类型的验证。
$ShouldParams = @{
Throw = $true
ExpectedMessage = "Cannot validate argument on parameter 'OutDir'. OutDir must be a folder path, not a file."
ExceptionType = ([System.Management.Automation.ParameterBindingException])
}
{ Test-Validation -Folder C:\Temp\file.txt } | Should @ShouldParams
概括一下您的 :
由于从给定实例开始处理对象类型在 PowerShell 中并不常见,实例的类型可能是 non-public 通常不明显,只要类型 派生自 (是子类)预期的 public类型。
- 虽然您可以通过
.GetType()
获取对象的非 public 类型 ,但您不能通过 类型文字引用它(例如 [System.Management.Automation.ParameterBindingException]
),例如用于 Pester 测试或参数声明。
您可以在任何给定实例上调用 .GetType().IsPublic
来检查其类型是否为 public,并调用 .GetType().BaseType
来获取该类型的基类型 - 尽管您可能必须调用后者 多个 类型,直到达到 .IsPublic
是 $true
的类型 - 请参阅底部的便利功能。
在手头的案例中 .GetType().BaseType.FullName
足以达到 public 基本类型:
# Provoke a non-public [System.Management.Automation.ParameterBindingValidationException]
# exception.
try { & { param([ValidateScript({ $false })] $foo)} bar } catch { $err = $_ }
# Output the full name of the exception type underlying the
# statement-terminating error that the failed validation reported:
$err.Exception.GetType().FullName
# It is only its *base* type that is public and therefore usable as a type
# literal ([...]), such as in a Pester test.
$err.Exception.GetType().BaseType.FullName
以上结果:
System.Management.Automation.ParameterBindingValidationException # non-public
System.Management.Automation.ParameterBindingException # public base type
下面是便利函数Get-PublicType
,给定任何实例,它报告实例类型的继承链中最派生的类型public(可能是实例的类型本身:
调用示例[=66=]:
PS> Get-PublicType $err.Exception
PublicType NonPublicDerivedType Instance
---------- -------------------- --------
System.Management.Automation.ParameterBindingException {System.Management.Automation.ParameterBindingValidationException} System.Management.Automation.ParameterBindingValidationException: Cannot validate argument on par…
Get-PublicType
源代码:
function Get-PublicType {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
$Instance
)
process {
$type = $Instance.GetType()
$nonPublicTypes = @()
while (-not $type.IsPublic) {
$nonPublicTypes += $type
$type = $type.BaseType
}
# $type.FullName
[pscustomobject] @{
PublicType = $type
NonPublicDerivedType = $nonPublicTypes
Instance = $Instance
}
}
}
给定一个对参数进行验证的函数:
function Test-Validation {
[CmdletBinding()]
param (
[Parameter()]
[ValidateScript({
# Add some validation that can throw.
if (-not (Test-Path -Path $_ -PathType Container)) {
throw "OutDir must be a folder path, not a file."
}
return $true
})]
[System.String]
$Folder
)
Process {
$Folder + " is a folder!"
}
}
我们应该能够检查错误类型并将其设置为纠缠测试中的 ExpectedType
。
Test-Validation -Folder C:\Temp\file.txt
Test-Validation : Cannot validate argument on parameter 'Folder'. OutDir must be a folder path, not a file.
At line:1 char:17
+ Test-Validation C:\Temp\file.txt
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Test-Validation], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Test-Validation
$Error[0].Exception.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False True ParameterBindingValidationException System.Management.Automation.ParameterBindingException
但是在Pester中测试时,由于找不到类型,测试失败。
$ShouldParams = @{
Throw = $true
ExpectedMessage = "Cannot validate argument on parameter 'OutDir'. OutDir must be a folder path, not a file."
ExceptionType = ([System.Management.Automation.ParameterBindingValidationException])
}
{ Test-Validation -Folder C:\Temp\file.txt } | Should @ShouldParams
# Result
RuntimeException: Unable to find type [System.Management.Automation.ParameterBindingValidationException].
我怎样才能修复这个测试,以便我知道我不仅仅是在捕获任何异常类型?
无法捕获此类型的原因是因为它不是 [System.Management.Automation]
中的 public class。相反,您可以将 -ExceptionType
设置为它派生自 [System.Management.Automation.ParameterBindingException]
的 class,您的测试现在将通过对抛出的异常类型的验证。
$ShouldParams = @{
Throw = $true
ExpectedMessage = "Cannot validate argument on parameter 'OutDir'. OutDir must be a folder path, not a file."
ExceptionType = ([System.Management.Automation.ParameterBindingException])
}
{ Test-Validation -Folder C:\Temp\file.txt } | Should @ShouldParams
概括一下您的
由于从给定实例开始处理对象类型在 PowerShell 中并不常见,实例的类型可能是 non-public 通常不明显,只要类型 派生自 (是子类)预期的 public类型。
- 虽然您可以通过
.GetType()
获取对象的非 public 类型 ,但您不能通过 类型文字引用它(例如[System.Management.Automation.ParameterBindingException]
),例如用于 Pester 测试或参数声明。
- 虽然您可以通过
您可以在任何给定实例上调用
.GetType().IsPublic
来检查其类型是否为 public,并调用.GetType().BaseType
来获取该类型的基类型 - 尽管您可能必须调用后者 多个 类型,直到达到.IsPublic
是$true
的类型 - 请参阅底部的便利功能。
在手头的案例中 .GetType().BaseType.FullName
足以达到 public 基本类型:
# Provoke a non-public [System.Management.Automation.ParameterBindingValidationException]
# exception.
try { & { param([ValidateScript({ $false })] $foo)} bar } catch { $err = $_ }
# Output the full name of the exception type underlying the
# statement-terminating error that the failed validation reported:
$err.Exception.GetType().FullName
# It is only its *base* type that is public and therefore usable as a type
# literal ([...]), such as in a Pester test.
$err.Exception.GetType().BaseType.FullName
以上结果:
System.Management.Automation.ParameterBindingValidationException # non-public
System.Management.Automation.ParameterBindingException # public base type
下面是便利函数Get-PublicType
,给定任何实例,它报告实例类型的继承链中最派生的类型public(可能是实例的类型本身:
调用示例[=66=]:
PS> Get-PublicType $err.Exception
PublicType NonPublicDerivedType Instance
---------- -------------------- --------
System.Management.Automation.ParameterBindingException {System.Management.Automation.ParameterBindingValidationException} System.Management.Automation.ParameterBindingValidationException: Cannot validate argument on par…
Get-PublicType
源代码:
function Get-PublicType {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
$Instance
)
process {
$type = $Instance.GetType()
$nonPublicTypes = @()
while (-not $type.IsPublic) {
$nonPublicTypes += $type
$type = $type.BaseType
}
# $type.FullName
[pscustomobject] @{
PublicType = $type
NonPublicDerivedType = $nonPublicTypes
Instance = $Instance
}
}
}