Search code examples
powershellpester

Testing for mandatory parameters with Pester


I'm trying to figure out how to have Pester test for parameters that are missing:

Find-Waldo.Tests.ps1

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'

Describe 'Mandatory paramters' {
    it  'ComputerName' {
        {
            $Params = @{
                #ComputerName = 'MyPc'
                ScriptName   = 'Test'
            }
            . "$here\$sut" @Params
        } | Should throw
    }
}

Find-Waldo.ps1

Param (
    [Parameter(Mandatory)]
    [String]$ComputerName,
    [String]$ScriptName
)

Function Find-Waldo {
    [CmdletBinding()]
    Param (
        [String]$FilePath
    )

    'Do something'
}

Every time I try to assert the result or simply run the test, it will prompt me for the ComputerName parameter instead of failing the test.

Am I missing something super obvious here? Is there a way to test for the presence of mandatory parameters?


Solution

  • Per the comments from Mathias, you can't really test for whether a Mandatory parameter is missing because PowerShell prompts for it rather than throwing an error. Per the comment he linked to from the Pester team you could use Get-Command to test for the Mandatory parameter setting in the script (assuming it is the only parameter attribute set for that variable)

    ((Get-Command "$here\$sut").Parameters['ComputerName'].Attributes.Mandatory | Should Be $true
    

    An alternative option would be to not use Mandatory parameters in this instance, and instead have a script block that does a Throw as the default value of the parameter:

    Param (
        [String]$ComputerName = $(Throw '-ComputerName is required'),
        [String]$ScriptName
    )
    

    If the script is always used as part of an automated process (instead of via user execution) this might be preferred as it allows you to control/capture its behavior and avoids it getting stuck during execution. You can then test the script as you had originally proposed:

    Describe 'Mandatory paramters' {
        it  'ComputerName' {
            {
                $Params = @{
                    #ComputerName = 'MyPc'
                    ScriptName   = 'Test'
                }
                . "$here\$sut" @Params
            } | Should throw '-ComputerName is required'
        }
    }