【问题标题】:Testing for mandatory parameters with Pester使用 Pester 测试强制参数
【发布时间】:2023-03-28 02:47:01
【问题描述】:

我试图弄清楚如何让 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 参数,而不是使测试失败。

我在这里遗漏了一些非常明显的东西吗?有没有办法测试强制参数的存在?

【问题讨论】:

  • 您不应该尝试以这种方式测试Mandatory 属性,as per this comment from the team
  • 你能举个例子说明如何在上面的例子中使用((Get-Command Get-Command).Parameters['Name'].Attributes | ? { $_ -is [parameter] }).Mandatory | Should Be $false吗?
  • Get-Command 也适用于脚本文件:(Get-Command "$here\$sut").Parameters
  • 谢谢 Mathias,我已经这样解决了 (Get-Command "$here\$sut").Parameters['ComputerName'].Attributes.Mandatory | Should be $true 如果您发布此问题,我会将其标记为已解决。

标签: powershell pester


【解决方案1】:

根据 Mathias 的 cmets,您无法真正测试是否缺少强制参数,因为 PowerShell 会提示输入它而不是引发错误。根据comment he linked to from the Pester team,您可以使用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'
    }
}

【讨论】:

    【解决方案2】:

    虽然接受的答案表明这是不可能的,但实际上是可能的。这是我为解决这个问题而开发的解决方案。

    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 cmdlet 无法完成工作,因为一个或多个作业被阻止等待用户交互。使用 Receive-Job cmdlet 处理交互式作业输出,然后重试。

    您会注意到我硬编码了模块的文件系统路径。我不确定如何将此作为参数传递给 Pester 为我们调用的“外部”ScriptBlock。也许有人对如何完成最后一块拼图有建议。

    PowerShell 后台作业的独特之处在于,您实际上可以恢复处于Blocked 状态的作业,并且它会提示您输入,即使它抛出了之前的异常。 p>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多