Reputation: 183
I'm learning slowly using the wonderful Pester unit testing for Powershell for a while now. I'm kind of stuck around the usage of checking if my function can run "if not supplied any mandatory input into a function." which is giving me a red light here and wanted to achieve a green test result and move on coding.
So I have a function as follows.
function Code()
{
param(
[parameter(Mandatory=$true)]
[string]$SourceLocation)
return "Hello from $SourceLocation"
}
my test script is executed with the following checks ...
$moduleName = 'Code';
Describe $moduleName {
Context "$Function - Returns a result " {
It "does something useful with just $Function function name" {
$true | Should Be $true
}
}
Context "$Function - Returns with no input " {
It "with no input returns Mandatory value expected" {
Code | Should Throw
}
}
Context "$Function - Returns some output" {
It "with a name returns the standard phrase with that name" {
Code "Venus" | Should Be "Hello from Venus"
}
It "with a name returns something that ends with name" {
Code "Mars" | Should Match ".*Mars"
}
}
} #End Describe
my output from AppVeyor shows this outcome which the [+] are green colours and [-] is a red colour which is what I'm avoiding the best I can.
Describing Code
Context Code - Returns a result
[+] does something useful with just Code function name 16ms
Context Code - Returns with no input
[-] with no input returns Mandatory value expected 49ms
Cannot process command because of one or more missing mandatory parameters: SourceLocation.
at <ScriptBlock>, C:\projects\code\Code.Tests.ps1: line 117
117: Code | Should Throw
Context Code - Returns some output
[+] with a name returns the standard phrase with that name 23ms
[+] with a name returns something that ends with name 11ms
Any help is appreciated as I would like a green condition there as I'm not sure how to overcome certain types of message responses from Powershell and translate this into unit tests...
Upvotes: 1
Views: 1078
Reputation: 23395
Per the comment from TessellatingHeckler, your code isn't working because in order to test for Throw
you need to pipe the Should
cmdlet a scriptblock { }
:
{Code} | Should Throw
It's worth noting however that (when testing for a mandatory parameter) this works OK in AppVeyor because PowerShell is running in a non-interactive console (PowerShell.exe -noninteractive
). If you try to run your Pester tests locally, your tests will seemingly be interrupted as you get prompted for input.
There's a couple of ways around this, one is to just run your tests locally using PowerShell in noninteractive mode:
PowerShell.exe -noninteractive {Invoke-Pester}
Another is to pass the parameter an explicit $null
or empty value (with the caveat that you can actually have a mandatory string parameter that accepts $null
and this solution won't work necessarily with all other parameter types):
It "with no input returns Mandatory value expected" {
{Code $null} | Should Throw
}
However it is worth noting that these two solutions throw different exception messages, and you should further test for an explicit message for the Throw
so that your test doesn't pass if the code is failing for some other reason. E.g:
Running with -noninteractive
It "with no input returns Mandatory value expected" {
{Code} | Should Throw 'Cannot process command because of one or more missing mandatory parameters: SourceLocation.'
}
Passing it $null
It "with no input returns Mandatory value expected" {
{Code $null} | Should Throw "Cannot bind argument to parameter 'SourceLocation' because it is an empty string."
}
In summary this is only a complex issue for this specific scenario because your parameter is mandatory and you're testing for its absence.
Testing for exceptions is generally a simple process of:
{ some code } | should Throw 'message'
And works fine in both an interactive and non-interactive console.
Upvotes: 2