我如何 Powershell Pester 测试 ThrowTerminatingError

Eri*_*unn 4 testing powershell pester

我如何 Powershell Pester 测试 ThrowTerminatingError ?

catch
{
    $PSCmdlet.ThrowTerminatingError( $PSItem )
}
Run Code Online (Sandbox Code Playgroud)

输出:

Missed command:

File                  Class Function          Line Command
----                  ----- --------          ---- -------
Test-ServerOnline.ps1       Test-ServerOnline   50 $PSCmdlet.ThrowTerminatingError( $PSItem )
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 8

为了在 Pester 测试中捕获终止错误(异常)

  • 您必须将输入命令括在脚本块( { ... }) 中

  • 并测试这样的错误是否/没有发生
    Should -Throw/Should -Not -Throw

注意:如果你也想处理非终止错误这种方式,Should -Throw没有处理:

  • 如果输入命令调用 cmdlet / 高级函数,则向其添加通用参数-ErrorAction Stop,这会将(第一个)非终止错误提升为(脚本)终止(致命)错误。

  • 否则,设置$ErrorActionPreference = 'Stop'脚本块内的第一条语句。


例子

注意:为简洁起见,以下代码片段不是完整的 Pester 测试,仅调用 Pester Shouldcmdlet;但是,您可以按原样调用它们,在这种情况下,不接收输出就意味着测试成功。有关完整示例,请参阅底部部分。

# Note the { ... } around the command.
{ 1 / 0 } | Should -Throw
Run Code Online (Sandbox Code Playgroud)

上面的测试通过了,因为1 / 0创建了一个语句终止错误,它与$PSCmdlet.ThrowTerminatingError()产生的错误类型相同。

随着非终止错误升级为一个终止-ErrorAction Stop

# Note: Without -ErrorAction Stop, the test would fail, because
#       not finding a file is a non-terminating error.
{ Get-Item NoSuchFile -ErrorAction Stop } | Should -Throw
Run Code Online (Sandbox Code Playgroud)

此外,您可以使用以下参数测试特定的错误 ID-ErrorId

{ 1 / 0 } | Should -Throw -ErrorId RuntimeException
Run Code Online (Sandbox Code Playgroud)

上面的测试通过了,因为由 触发的语句终止错误产生的错误记录1 / 0(也记录在自动$Error变量中),其.FullyQualifiedErrorId值为RuntimeException(verify with $Error[0].FullyQualifiedErrorIdafter)。

注意:-ErrorId执行字面子字符串匹配,因此-ErrorId Runtime在上面的命令中也可以使用。

或者,您可以使用参数测试特定的异常类型-ExceptionType

{ 1 / 0 } | Should -Throw -ExceptionType System.Management.Automation.RuntimeException
Run Code Online (Sandbox Code Playgroud)

请注意,您必须传递完整的类型名称;省略System.组件(PowerShell 通常允许)-ExceptionType.

要识别与最近错误关联的异常类型,请使用 $Error[0].Exception.GetType().FullName


完整示例

将以下内容存储在*.tests.ps1文件中并直接或通过Invoke-Pester.
所有这些测试都应该通过。

Describe "Error-handling tests" {

  BeforeAll {
    # Define an advanced function that generates a terminating error.
    function Get-FooTerminating {
      [CmdletBinding()]
      param()
      # When invoked by Pester, $PSCmdlet.ThrowTerminatingError()
      # would have the same effect here, but note that $PSCmdlet.ThrowTerminatingError()
      # creates a *statement*-terminating error, whereas Throw creates a more
      # severe *script*-terminating (thread-terminating) error.
      Throw "me for a loop"
    }
    
    # Define an advanced function that generates a non-terminating error.
    function Get-FooNonTerminating {
      [CmdletBinding()]
      param()
      Write-Error "Something went mildly wrong."
    }

  }

  It "A terminating error throws." {
    { Get-FooTerminating } | Should -Throw
  }

  It "A non-terminating error doesn't throw." {
    # Note: Non-terminating errors are *passed through*, so
    #       we silence them with 2>$null here.
    { Get-FooNonTerminating 2>$null } | Should -Not -Throw
  }

  It "A non-terminating error promoted to a terminating one does throw." {
    { Get-FooNonTerminating -ErrorAction Stop } | Should -Throw
  }

  It "A fully qualified error ID can be tested for." {
    # Test for a (substring of) the error record's .FullyQualifiedErrorId 
    { NoSuchCommand } | Should -Throw -ErrorId CommandNotFound
  }

  It "A specific exception type can be tested for." {
    # Note the need to specify the type name *in full*, including the
    # 'System.' part
    { NoSuchCommand } | Should -Throw -ExceptionType System.Management.Automation.CommandNotFoundException
  }


}
Run Code Online (Sandbox Code Playgroud)