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 )
In order to catch a terminating error (an exception) in a Pester test:
you must enclose the input command in a script block ({ ... }
)
and test for whether such an error did / did not occur with Should -Throw
/ Should -Not -Throw
Note: If you also want to handle non-terminating errors this way, which Should -Throw
does not handle:
If the input command calls a cmdlet / advanced function, add common parameter -ErrorAction Stop
to it, which promotes the (first) non-terminating error to a (script)-terminating (fatal) one.
Otherwise, set $ErrorActionPreference = 'Stop'
as the first statement inside the script block.
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
}
}