简体   繁体   中英

Pester unit testing function with Mandatory=True

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...

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. Eg:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM