Pester 没有捕捉到抛出的错误
Pester doesn't catch the thrown error
当我 运行 下面的纠缠测试时,我希望它能捕捉到预期的错误,但它没有。但是当我 运行 使用不同的函数和不同的 throw 语句进行测试时,它就起作用了。
纠缠测试:
Describe "Remove-GenericCredential Function Tests" {
$InternetOrNetworkAddress = 'https://PesterTestUser@PesterTestURl.com'
Context "Test: Remove-GenericCredential -InternetOrNetworkAddress '$InternetOrNetworkAddress' (Credential does not exist)" {
It "This Command threw an error. The credential does not exist." { { (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false) } | should throw "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found" }
}
}
未捕获的错误:
Remove-GenericCredential : Credential https://PesterTestUser@PesterTestURl.com not found
At C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\Remove-GenericCredential.Tests.ps1:30 char:76
+ ... xist." { { (Remove-GenericCredential -InternetOrNetworkAddress $Inter ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-GenericCredential
[-] This Command threw an error. The credential does not exist. 44ms
Expected: the expression to throw an exception with message {Remove-GenericCredential : Credential https://PesterTestUser@PesterTestURl.com not found}, an exception was not raised, message was {}
from C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\New-GitHubCredential.Tests.ps1:59 char:176
+ ... e $UserName -Token 'NotAGitHubTokenSpecialCharacters!@#$%^&*') } | sh ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at <ScriptBlock>, C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\Remove-GenericCredential.Tests.ps1: line 30
30: It "This Command threw an error. The credential does not exist." { { (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false) } | should throw 'Remove-GenericCredential : Credential https://PesterTestUser@PesterTestURl.com not found' }
这可能是因为 cmdlet 抛出了 non-terminating 错误,因为 Pester 仅断言终止错误。在这种情况下,需要按如下方式重写测试(根据您的示例使用旧的 Pester v3 语法):
It "Test a non-terminating error gets thrown" {
$errorThrown = $false;
try
{
Invoke-CmdletThatThrowsNonTerminatingError -ErrorAction Stop
}
catch
{
$errorThrown = $true
}
$errorThrown | Should Be $true
}
在 catch 块中,您还可以获得异常详细信息,例如 $_
ob
上的消息或异常类型
根据另一个答案,该函数抛出 non-terminating error,因此它不被认为与正在检查终止错误的 Should Throw
的测试相匹配。
您可以通过两种方式解决此问题:
- 您可以更改它,以便通过将
Write-Error
更改为 Throw
来引发终止错误。
- 您可以更改测试以强制函数抛出终止错误,即使在调用它时使用
-ErrorAction Stop
发生 non-terminating 错误(我可以看到您正在使用 -Confirm
,我假设你已经在函数中使用 [cmdletbinding()]
来添加常用参数,如 -ErrorAction
)。
这是第二种解决方案的示例(我已经在顶部模拟了该函数,以便我可以对其进行测试,但您不需要将其包含在测试脚本中):
Function Remove-GenericCredential {
[cmdletbinding(supportsshouldprocess)]
Param(
$InternetOrNetworkAddress
)
Write-Error "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found"
}
Describe "Remove-GenericCredential Function Tests" {
$InternetOrNetworkAddress = 'https://PesterTestUser@PesterTestURl.com'
Context "Test: Remove-GenericCredential -InternetOrNetworkAddress '$InternetOrNetworkAddress' (Credential does not exist)" {
It "This Command threw an error. The credential does not exist." {
{ (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false -ErrorAction Stop) } | should throw "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found" }
}
}
来自help Write-Error
:
The Write-Error cmdlet declares a non-terminating error. By default,
errors are sent in the error stream to the host program to be
displayed, along with output.
To write a non-terminating error, enter an error message string, an ErrorRecord object, or an Exception object. Use the other parameters of Write-Error to populate the error record.
Non-terminating errors write an error to the error stream, but they do not stop command processing. If a non-terminating error is declared on one item in a collection of input items, the command continues to process the other items in the collection.
To declare a terminating error, use the Throw keyword. For more information, see about_Throw
(http://go.microsoft.com/fwlink/?LinkID=145153).
当我 运行 下面的纠缠测试时,我希望它能捕捉到预期的错误,但它没有。但是当我 运行 使用不同的函数和不同的 throw 语句进行测试时,它就起作用了。
纠缠测试:
Describe "Remove-GenericCredential Function Tests" {
$InternetOrNetworkAddress = 'https://PesterTestUser@PesterTestURl.com'
Context "Test: Remove-GenericCredential -InternetOrNetworkAddress '$InternetOrNetworkAddress' (Credential does not exist)" {
It "This Command threw an error. The credential does not exist." { { (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false) } | should throw "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found" }
}
}
未捕获的错误:
Remove-GenericCredential : Credential https://PesterTestUser@PesterTestURl.com not found
At C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\Remove-GenericCredential.Tests.ps1:30 char:76
+ ... xist." { { (Remove-GenericCredential -InternetOrNetworkAddress $Inter ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-GenericCredential
[-] This Command threw an error. The credential does not exist. 44ms
Expected: the expression to throw an exception with message {Remove-GenericCredential : Credential https://PesterTestUser@PesterTestURl.com not found}, an exception was not raised, message was {}
from C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\New-GitHubCredential.Tests.ps1:59 char:176
+ ... e $UserName -Token 'NotAGitHubTokenSpecialCharacters!@#$%^&*') } | sh ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at <ScriptBlock>, C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\Remove-GenericCredential.Tests.ps1: line 30
30: It "This Command threw an error. The credential does not exist." { { (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false) } | should throw 'Remove-GenericCredential : Credential https://PesterTestUser@PesterTestURl.com not found' }
这可能是因为 cmdlet 抛出了 non-terminating 错误,因为 Pester 仅断言终止错误。在这种情况下,需要按如下方式重写测试(根据您的示例使用旧的 Pester v3 语法):
It "Test a non-terminating error gets thrown" {
$errorThrown = $false;
try
{
Invoke-CmdletThatThrowsNonTerminatingError -ErrorAction Stop
}
catch
{
$errorThrown = $true
}
$errorThrown | Should Be $true
}
在 catch 块中,您还可以获得异常详细信息,例如 $_
ob
根据另一个答案,该函数抛出 non-terminating error,因此它不被认为与正在检查终止错误的 Should Throw
的测试相匹配。
您可以通过两种方式解决此问题:
- 您可以更改它,以便通过将
Write-Error
更改为Throw
来引发终止错误。 - 您可以更改测试以强制函数抛出终止错误,即使在调用它时使用
-ErrorAction Stop
发生 non-terminating 错误(我可以看到您正在使用-Confirm
,我假设你已经在函数中使用[cmdletbinding()]
来添加常用参数,如-ErrorAction
)。
这是第二种解决方案的示例(我已经在顶部模拟了该函数,以便我可以对其进行测试,但您不需要将其包含在测试脚本中):
Function Remove-GenericCredential {
[cmdletbinding(supportsshouldprocess)]
Param(
$InternetOrNetworkAddress
)
Write-Error "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found"
}
Describe "Remove-GenericCredential Function Tests" {
$InternetOrNetworkAddress = 'https://PesterTestUser@PesterTestURl.com'
Context "Test: Remove-GenericCredential -InternetOrNetworkAddress '$InternetOrNetworkAddress' (Credential does not exist)" {
It "This Command threw an error. The credential does not exist." {
{ (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false -ErrorAction Stop) } | should throw "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found" }
}
}
来自help Write-Error
:
The Write-Error cmdlet declares a non-terminating error. By default, errors are sent in the error stream to the host program to be displayed, along with output.
To write a non-terminating error, enter an error message string, an ErrorRecord object, or an Exception object. Use the other parameters of Write-Error to populate the error record.
Non-terminating errors write an error to the error stream, but they do not stop command processing. If a non-terminating error is declared on one item in a collection of input items, the command continues to process the other items in the collection.
To declare a terminating error, use the Throw keyword. For more information, see about_Throw (http://go.microsoft.com/fwlink/?LinkID=145153).