Closed dotps1 closed 9 years ago
My-FunctionThatWritesErrorForInvalidPath -Path '.\InvalidPath' | Should Throw
Should Throw
only works for terminating errors, so you can do one of two things. You can either use -ErrorAction Stop
to force your non-terminating errors to become terminating (though this would prevent your End block from running), or you can use something like -ErrorVariable
and then do assertions against that. Something along these lines:
It 'Error should be raised' {
My-FunctionThatWritesErrorForInvalidPath -Path '.\InvalidPath' -ErrorVariable err
$err.Count | Should Not Be 0
$err[0].Exception.Message | Should Be "Path '.\InvalidPath' is not valid" # or something like that
}
# or
It 'Error should be raised' {
$scriptBlock = { My-FunctionThatWritesErrorForInvalidPath -Path '.\InvalidPath' -ErrorAction Stop }
$scriptBlock | Should Throw "Path '.\InvalidPath' is not valid" # or something like that
}
thanks Dave, that works fine for me! keep up the good work! feel free to close this thread if you wish.
Ah, sorry, I didn't read the question all the way through. I personally always throw and then run cleanup code in finally
. I see you're using a different (and valid) approach.
I work around this with two helper functions that I call in all my tests:
Function InvokeShouldFail
{
Param([Parameter(Mandatory)][string]$script)
Write-Host Invoking command and expecting failure: $script
$didFail = $false
try
{
iex $script
Write-Warning Did not fail: $script
}
catch
{
Write-Host "Script failed as expected: $_"
$didFail = $true
}
$didFail | Should Be $true
}
Function InvokeShouldError {
Param([Parameter(Mandatory)][string]$script)
Write-Host Invoking command and expecting error: $script
$didError = ""
iex $script -ErrorVariable didError
Write-Host Error result: $didError
$didError | Should Not BeNullOrEmpty
}
Then in my unit test, I call it something like this
It "Does something" {
# This should fail, but not with a thrown exception
InvokeShouldError { Remove-Something -Name NotReallyExist }
}
I ran into this as well. Thanks for the help.
Should Throw
only works for terminating errors, so you can do one of two things. You can either use-ErrorAction Stop
to force your non-terminating errors to become terminating (though this would prevent your End block from running), or you can use something like-ErrorVariable
and then do assertions against that. Something along these lines:It 'Error should be raised' { My-FunctionThatWritesErrorForInvalidPath -Path '.\InvalidPath' -ErrorVariable err $err.Count | Should Not Be 0 $err[0].Exception.Message | Should Be "Path '.\InvalidPath' is not valid" # or something like that } # or It 'Error should be raised' { $scriptBlock = { My-FunctionThatWritesErrorForInvalidPath -Path '.\InvalidPath' -ErrorAction Stop } $scriptBlock | Should Throw "Path '.\InvalidPath' is not valid" # or something like that }
Thanks so much for these tips, very helpful.
Just one little note. The first solution will still display the error on the screen which may be rather distracting while running Pester. You may simply add -ErrorAction SilentlyContinue
to avoid this happening.
I like the first approach as it also allows you to validate return values.
e.g.
Describe 'Get-RelativePath' {
Context 'Filesystem Paths' {
It 'Should return a relative path when given absolute paths' {
$relativePath = Get-RelativePath `
-Path 'C:\wow\files\my app' `
-BasePath 'HKLM:\SOFTWARE\my app' `
-ErrorVariable errors `
-ErrorAction SilentlyContinue
$errors.Count | Should Be 1
$errors[0].Exception.Message | Should Be (
'The scheme of the path and base path provided do not match.'
)
$relativePath | Should Be $null
}
}
...
Cheers Fotis
I believe this is probably a pretty common scenario, so I updated the Should
documentation to include a blurb about it in the Throw
example, with a link back to this issue 🙂
I know I'm new and this may be obvious to those who have used this a lot before, but doesn't the stop
keyword in the code blocks above need to be in quotes?
In any case, I ran into a situation where I wanted to test that a warning was printing, so I had to make use of the piping operator to test:
Describe 'Get-RelativePath' {
Context 'Filesystem Paths' {
It 'Should return a warning when given incorrect paths' {
$temporaryFile - $PSScriptRoot + '\notARealFile.txt'
New-Item -Path $temporaryFile -ItemType 'file' -Force
Get-RelativePath -Path 'C:\invalid\path' 3> $temporaryFile
$temporaryFile | Should -not -BeNullOrEmpty
$temporaryFile | Should Be ( 'your Error Message here' )
}
}
All this does is pipe all the errors to a file named 'notARealFile.txt' that you can then check yourself.
doesn't the
stop
keyword in the code blocks above need to be in quotes?
No. -ErrorAction
is of type enum (a pre-defined list of values) and not a string. Even if it was a string parameter, values without whitespace are usually okay (fixed automatically by powershell).
All this does is pipe all the errors to a file named 'notARealFile.txt' that you can then check yourself.
You are actually saving warnings (stream 3), not errors. So this is unrelated to the issue. Tip: If this command is a "advanced function" (ex specifies [CmdLetBinding()]
), then you can use Get-RelativePath -Path 'C:\invalid\path' -WarningVariable mywarnings
to catch the warnings. If not and if the command shouldn't return any other output in this test that you need, then you can redirect warnings to standard output and store in a variable like normal results, ex $myWarnings = Get-RelativePath -Path 'C:\invalid\path' 3>&1
Thanks for the -ErrorAction
clarification. And piping to a variable would be a better idea for my use case, thanks.
I reviewed the Should Wiki Page, and i apologize if i missed how to use this, but i was working with some error handling, and i want to Pester for non terminating errors as well as Exceptions. Basically, i have some tests in a function that are in the Process block, and i still want the End block to process, so in this case i want to use Write-Error rather then Throw, so, in my pester assertion, i want to make sure the Catch block is being hit, and the Write-Error is being executed, and im not sure how to do that.
I hope that makes sense and im sorry if im just using Write-Error incorrectly, and i could use the 'Should Throw' assertion.
thanks for any help.