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 的测试相匹配。

您可以通过两种方式解决此问题:

  1. 您可以更改它,以便通过将 Write-Error 更改为 Throw 来引发终止错误。
  2. 您可以更改测试以强制函数抛出终止错误,即使在调用它时使用 -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).