Get-ParameterValues
,签字人
@Jaykul
,以及
elovelan
. 我选择使用elovelan的不声明参数的版本。我可以确认,就我在命令行进行的测试而言,该函数按预期工作。
我将这个函数合并到一个私有模块中,我将它作为一个通用函数来编写(当然要有适当的属性,谢谢
@杰库尔
和
!!),因此,我正试图为它编写单元测试。但是,当运行测试时,我得到了错误
Cannot find a variable with the name 'PSBoundParameters'.
纠缠测试因错误而失败
找不到名为“PSBoundParameters”的变量。
here
文件功能
Feature: Get-ParameterValues
As a PowerShell function author
In order to more easily deal with function parameters
I want to be able to automatically populate a dictionary
containing the supplied function arguments or the parameter's
default value if the argument was not supplied
So that I can reduce boilerplate code when dealing with
function parameters.
Background: A test function with parameters
Given a test function
"""
function global:Test {
[CmdletBinding()]
param(
[Parameter(Position = 0)]
$ValueWithNoDefault,
[Parameter(Position = 1)]
$ValueWithDefault = 'default',
[Parameter(Position = 2)]
$ValueWithNullDefault = $null
)
$Parameters = (Get-ParameterValues)
$Parameters
}
"""
Scenario Outline: Get-ParameterValues returns a dictionary with the expected key and value
Given the value '<Value>' is provided for the '<Parameter>' parameter
When 'global:Test' is invoked
Then the hashtable '<ContainsAKey>' a key for the parameter
And the resolved parameter value is '<ExpectedValue>'.
Examples: Examples using parameter ValueWithNoDefault
| Parameter | Value | Contains | ExpectedValue |
| ValueWithNoDefault | <No value> | does not contain | <Does Not Exist> |
| ValueWithNoDefault | `$null | contains | `$null |
| ValueWithNoDefault | { `$foo = 1 } | contains | { `$foo = 1 } |
| ValueWithNoDefault | `$false | contains | `$false |
| ValueWithNoDefault | `$true | contains | `$true |
| ValueWithNoDefault | "" | contains | "" |
| ValueWithNoDefault | 0 | contains | 0 |
| ValueWithNoDefault | @() | contains | @() |
| ValueWithNoDefault | 1 | contains | 1 |
步骤定义
BeforeEachFeature {
Import-Module -Name "${pwd}\path-to\My-Module.psd1" -Scope Global -Force
filter global:ConvertFrom-TableCellValue {
Param(
[Parameter(Mandatory=$True, Position=0, ValueFromPipeline=$True)]
[AllowNull()]
[AllowEmptyString()]
$Value
)
Process {
if ($Value -eq '$null') {
$Value = $null
}
switch -Regex ($Value) {
'^"?\{\s*(?<ScriptBody>.*)\s*\}"?$' { $Value = [ScriptBlock]::Create($Matches.ScriptBody) }
'(?<StringValue>".*")' { $Value = ($Matches.StringValue -as [string]) }
'$?(?i:(?<Boolean>true|false))' { $Value = [Boolean]::Parse($Matches.Boolean) }
'^\d+$' { $Value = $Value -as [int] }
default { }
}
$Value
}
}
}
AfterEachFeature {
$Module = Get-Module -Name "My-Module"
if ($Module) {
$Module.Name | Remove-Module
}
if (Test-Path "Function:\global:ConvertTo-Parameter") {
Remove-Item Function:\global:ConvertTo-Parameter
}
}
Given "a test function" {
param ([string]$func)
Invoke-Expression $func
$f = Get-Item 'Function:\Test'
$f | Should -Not -BeNull
}
Given "the value '(?<Value>.*)' is provided for the '(?<Parameter>\S*)' parameter" {
param(
[object]$Value,
[string]$Parameter
)
$Value = ConvertFrom-TableCellValue $Value
if ($Value -ne "<No value>") {
$Context = @{ $Parameter = $Value }
} else {
$Context = @{}
}
}
When "'(?<CmdletName>.*)' is invoked" {
[CmdletBinding()]
Param ([string]$CmdletName)
# NOTE: I probably don't need the if block, but I added this during debugging of this issue...just-in-case.
# NOTE: The test fails in this step definition at this point when it executes the `Test` function which calls Get-ParameterValues.
if ($Context.Keys.Count -gt 0) {
$actual = &$CmdletName @Context
} else {
$actual = &$CmdletName
}
Write-Debug $actual.GetType().FullName
}
Then "the hashtable '(?<ContainsAKey>(does not contain|contains))' a key for the parameter" {
param([string]$ContainsAKey)
($Context.ContainsKey($Parameter) -and $actual.ContainsKey($Context.$Parameter)) | Should -Be ($ContainsAKey -eq 'contains')
}
psake version 4.7.4
Copyright (c) 2010-2017 James Kovacs & Contributors
Executing InstallDependencies
Executing Init
Executing Test
Testing all features in 'C:\src\git\My-Module\Specs\features' with tags: 'Get-ParameterValues'
Feature: Get-ParameterValues
As a PowerShell function author
In order to more easily deal with function parameters
I want to be able to automatically populate a dictionary
containing the supplied function arguments or the parameter's
default value if the argument was not supplied
So that I can reduce boilerplate code when dealing with
function parameters.
Scenario: Get-ParameterValues returns a dictionary with the expected key and value
Examples:Examples using parameter ValueWithNoDefault
[+] Given a test function 59ms
[+] Given the value '<No value>' is provided for the 'ValueWithNoDefault' parameter 187ms
[-] When 'global:Test' is invoked 48ms
at <ScriptBlock>, C:\src\git\My-Module\Public\Utility\Get-ParameterValues.ps1: line 74
74: $BoundParameters = Get-Variable -Scope 1 -Name PSBoundParameters -ValueOnly
From C:\src\git\My-Module\Specs\features\Utility\Get-ParameterValues.feature: line 35
Cannot find a variable with the name 'PSBoundParameters'.
[-] Then the hashtable 'does not contain' a key for the parameter 201ms
at <ScriptBlock>, C:\src\git\My-Module\Specs\features\steps\Utility\Get-ParameterValues.steps.ps1: line 38
38: ($Context.ContainsKey($Parameter) -and $actual.ContainsKey($Context.$Parameter)) | Should -Be ($ContainsAKey -eq 'contains')
From C:\src\git\My-Module\Specs\features\Utility\Get-ParameterValues.feature: line 36
You cannot call a method on a null-valued expression.
[?] And the resolved parameter value is '<Does Not Exist>'. 40ms
Could not find implementation for step!
At And, C:\src\git\My-Module\Specs\features\Utility\Get-ParameterValues.feature: line 37
谁能告诉我为什么
$PSBoundParameters
字典不存在于
函数,即使参数传递给
Test
功能?(我觉得这可能与PowerShell范围界定规则有关,因为
When
脚本块有“脚本”范围——我试图通过确保
函数在中声明
global
更新
所以,沿着这条路走下去可能是PowerShell作用域的问题,我只是不明白,我修改了我的小黄瓜
Given
步骤如下:
Given a test function
"""
function global:Test {
[CmdletBinding()]
param(
[Parameter(Position = 0)]
$ValueWithNoDefault,
[Parameter(Position = 1)]
$ValueWithDefault = 'default',
[Parameter(Position = 2)]
$ValueWithNullDefault = $null
)
$DebugPreference = 'Continue'
if ($PSBoundParameters) {
Write-Debug "`$PSBoundParameters = $(ConvertTo-JSON $PSBoundParameters)"
} else {
Write-Debug "Unable to find `$PSBoundParameters automatic variable."
}
$Parameters = (Get-ParameterValues)
$Parameters
}
"""
下面是对前两个表项运行测试的输出(请参阅上面的原始功能文件):
psake version 4.7.4
Copyright (c) 2010-2017 James Kovacs & Contributors
Executing InstallDependencies
Executing Init
Executing Test
Testing all features in 'C:\src\git\My-Module\Specs\features' with tags: 'Get-ParameterValues'
Feature: Get-ParameterValues
As a PowerShell function author
In order to more easily deal with function parameters
I want to be able to automatically populate a dictionary
containing the supplied function arguments or the parameter's
default value if the argument was not supplied
So that I can reduce boilerplate code when dealing with
function parameters.
Scenario: Get-ParameterValues returns a dictionary with the expected key and value
Examples:Examples using parameter ValueWithNoDefault
[+] Given a test function 54ms
DEBUG: $Parameter: ValueWithNoDefault
DEBUG: $Value: <No value>
[+] Given the value '<No value>' is provided for the 'ValueWithNoDefault'
parameter 29ms
DEBUG: Cmdlet: Test
DEBUG: Context: {
}
DEBUG: $PSBoundParameters = {
}
[-] When 'Test' is invoked 47ms
at <ScriptBlock>, C:\src\git\My-Module\Public\Utility\Get-ParameterValues.ps1: line 74
74: $BoundParameters = Get-Variable -Scope 1 -Name PSBoundParameters -ValueOnly
From C:\src\git\My-Module\Specs\features\Utility\Get- ParameterValues.feature: line 41
Cannot find a variable with the name 'PSBoundParameters'.
DEBUG: Context: {
}
DEBUG: actual:
[+] Then the hashtable 'does not contain' a key for the parameter 61ms
[?] And the resolved parameter value is '<Does Not Exist>'. 30ms
Could not find implementation for step!
At And, C:\src\git\My-Module\Specs\features\Utility\Get-ParameterValues.feature: line 43
DEBUG: $Parameter: ValueWithNoDefault
DEBUG: $Value:
[+] Given the value '$null' is provided for the 'ValueWithNoDefault' parameter 14ms
DEBUG: Cmdlet: Test
DEBUG: Context: {
"ValueWithNoDefault": ""
}
DEBUG: $PSBoundParameters = {
"ValueWithNoDefault": ""
}
[-] When 'Test' is invoked 9ms
at <ScriptBlock>, C:\src\git\My-Module\Public\Utility\Get-ParameterValues.ps1: line 74
74: $BoundParameters = Get-Variable -Scope 1 -Name PSBoundParameters -ValueOnly
From C:\src\git\My-Module\Specs\features\Utility\Get-ParameterValues.feature: line 41
Cannot find a variable with the name 'PSBoundParameters'.
DEBUG: Context: {
"ValueWithNoDefault": ""
}
DEBUG: actual:
[-] Then the hashtable 'contains' a key for the parameter 20ms
at <ScriptBlock>, C:\src\git\My- Module\Specs\features\steps\Utility\Get-ParameterValues.steps.ps1: line 39
39: ($Context.ContainsKey('Parameter') -and
$actual.ContainsKey($Context.$Parameter)) | Should -Be ($ContainsAKey -eq 'contains')
From C:\src\git\My-Module\Specs\features\Utility\Get-ParameterValues.feature: line 42
Expected $true, but got $false.
[?] And the resolved parameter value is '`$null'. 5ms
Could not find implementation for step!
At And, C:\src\git\My-Module\Specs\features\Utility\Get-ParameterValues.feature: line 43
$PSBoundParameters
试验
在中创建的函数
鉴于
只有当它是非null/empty/是“truthy”时才执行步骤(否则我会写一个字符串来说明它不存在)。在任何情况下,即使是在
$null
分配给参数,
定义并存在于
试验
获取参数值
在该函数内部尝试检索
$PSBoundParameters
试验
已确定变量存在于该范围内的函数)。但是,我从Pester测试步骤定义中得到了错误消息。不幸的是,这些结果让我更加困惑。