powershelltestingpester

How do I Powershell Pester Test for ThrowTerminatingError


How do I Powershell Pester Test for ThrowTerminatingError ?

catch
{
    $PSCmdlet.ThrowTerminatingError( $PSItem )
}

Output:

Missed command:

File                  Class Function          Line Command
----                  ----- --------          ---- -------
Test-ServerOnline.ps1       Test-ServerOnline   50 $PSCmdlet.ThrowTerminatingError( $PSItem )

Solution

  • In order to catch a terminating error (an exception) in a Pester test:

    Note: If you also want to handle non-terminating errors this way, which Should -Throw does not handle:


    Examples:

    Note: For brevity, the following snippets aren't full Pester tests and call just the Pester Should cmdlet; however, you can call them as-is, which case a successful test is implied by receiving no output. See the bottom section for a complete example.

    # Note the { ... } around the command.
    { 1 / 0 } | Should -Throw
    

    The above test passes, because 1 / 0 creates a statement-terminating error, which is the same error type that $PSCmdlet.ThrowTerminatingError() produces.

    With a non-terminating error promoted to a terminating one with -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
    

    Additionally, you can test for specific error IDs, using the -ErrorId parameter:

    { 1 / 0 } | Should -Throw -ErrorId RuntimeException
    

    The above test passes, because the error record produced by the statement-terminating error triggered with 1 / 0 (as also recorded in the automatic $Error variable), has a .FullyQualifiedErrorId value of RuntimeException (verify with $Error[0].FullyQualifiedErrorId afterwards).

    Note: -ErrorId performs literal substring matching, so that -ErrorId Runtime would work too in the command above.

    Alternatively, you can test for specific exception types, using the -ExceptionType parameter:

    { 1 / 0 } | Should -Throw -ExceptionType System.Management.Automation.RuntimeException
    

    Note that you must pass the full type name; omitting the System. component (which PowerShell often allows) is not recognized by -ExceptionType.

    To identify the type of the exception associated with the most recent error, use $Error[0].Exception.GetType().FullName


    Complete example:

    Store the following in a *.tests.ps1 file and invoke it either directly or via Invoke-Pester.
    All of these tests should pass.

    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 
        # You may also use wildcard expressions, e.g. "*NotFound*"   
        { NoSuchCommand } | Should -Throw -ErrorId CommandNotFoundException
      }
    
      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
      }
    
    
    }