使用 Pester 测试必填参数

9

我正在尝试弄清楚如何让 Pester 测试缺失的参数:

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'
}

每次我尝试使用assert检查结果或者运行测试时,它都会提示我输入ComputerName参数而不是测试失败。
我是否忽略了什么非常明显的东西?有没有一种方法可以测试必需参数的存在?

3
根据团队的这条评论,你不应该以这种方式尝试测试“Mandatory”属性。 - Mathias R. Jessen
你能否举个例子说明如何在脚本中使用 ((Get-Command Get-Command).Parameters['Name'].Attributes | ? { $_ -is [parameter] }).Mandatory | Should Be $false,就像上面的例子一样? - DarkLite1
2
Get-Command works on script files as well: (Get-Command "$here\$sut").Parameters - Mathias R. Jessen
谢谢Mathias,我是这样解决的:(Get-Command "$here\$sut").Parameters['ComputerName'].Attributes.Mandatory | Should be $true 如果您发布了这个,我会标记为已解决。 - DarkLite1
2个回答

6

根据Mathias的评论,你无法测试必填参数是否缺失,因为PowerShell会提示而不是抛出错误。根据Pester团队链接的评论,你可以使用Get-Command在脚本中测试必填参数的设置(假设它是该变量设置的唯一参数属性)。

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

另一种选择是在此情况下不使用强制参数,而是使用脚本块将Throw作为参数的默认值:

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

如果脚本始终作为自动化流程的一部分使用(而不是通过用户执行),则这可能更受欢迎,因为它允许您控制/捕获其行为并避免在执行过程中出现卡顿。然后,您可以按照最初提议的方式测试脚本:

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

1

尽管被接受的答案表明这是不可能的,但实际上是有可能的。以下是我开发的解决此问题的解决方案。

It 'Should fail when no priority is specified, for a valid process name' {
    { 
        $ScriptBlock = {
            Import-Module -Name $args[0]
            Set-ProcessPriority -Name System
        }
        Start-Job -ScriptBlock $ScriptBlock -ArgumentList $HOME/git/ProcessPriority/src/ProcessPriority | Wait-Job | Receive-Job 
    } | Should -Throw
}

从上面的示例中,您会注意到以下内容:
被测试的代码已包装在 PowerShell 的 ScriptBlock 中
我们调用一个包含测试代码的 PowerShell 后台作业
我们等待后台作业完成,然后接收结果
如果运行 Get-Job 命令,您会注意到作业处于 Blocked 状态
由后台作业抛出的异常类似于以下内容:
Wait-Job 命令无法完成工作,因为一个或多个作业被阻止等待用户交互。请使用 Receive-Job 命令处理交互式作业输出,然后重试。
您会注意到我硬编码了模块的文件系统路径。我不确定如何将其作为参数传递到 Pester 为我们调用的“外部” ScriptBlock 中。也许有人对如何完成这最后一步有建议。
PowerShell 后台作业独特的有趣之处在于,您实际上可以恢复处于 Blocked 状态的作业,并提示您进行输入,即使它抛出了先前的异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接