为什么 Pester 不模拟带有两个参数的 cmdlet?
Why Pester does not mock a cmdlet with two parameters?
我正在尝试进行一些 Pester 测试,但出现奇怪的错误 "A positional parameter cannot be found"(对于私有 Python cmdlet),这是 Pester 的限制还是我下面的代码有问题?
TestModule.psm1
代码:
#public function:
Function Create-Db
{
[CmdletBinding()]
Param(
[Parameter(Mandatory, ValueFromPipeline)]
[string]$database
)
Python 'Files\create_db.py' '--DBMS=SQLSERVER -d $database'
}
#private (not exported) function:
Function Python
{
[CmdletBinding()]
Param(
[Parameter(Mandatory, Position=1)]
[string]$scriptFile,
[Parameter(Position=2)]
[string]$args
)
$python ='C:\Python27\python.exe'
Push-Location $PSScriptRoot
$python = Start-Process -FilePath $python -ArgumentList @($scriptFile,$args) -Wait -NoNewWindow -PassThru
if($python.ExitCode -ne 0)
{
throw "Python script", $scriptFile, "failed"
}
Pop-Location
}
函数的纠错代码:
$scriptDirectory = (Split-Path -Parent $MyInvocation.MyCommand.Path) -replace "Test$"
Import-Module $scriptDirectory\TestModule.psm1 -Force
Describe "Create-Db test" {
Context "Create database" {
Mock -ModuleName TestModule Python -Verifiable { return; }
Create-Db -database "test_database"
It "Python has been called" {
Assert-VerifiableMocks
}
}
}
当我执行测试代码时出现此错误:
Describing Create-Db test
Context Create database
[-] Error occurred in Context block 1.35s
ParameterBindingException: A positional parameter cannot be found that accepts argument '--DBMS SqlServer -d test_database'.
at Test-ParameterFilter, C:\Program Files\WindowsPowerShell\Modules\Pester.3.14\Functions\Mock.ps1: line 1086
$args
是一个自动变量,它包含非高级函数的所有非绑定参数。 Pester 对此进行了解释。当调用模拟命令时,Pester 捕获 $PSBoundParameters
和 $args
作为传递参数的指示。后来 Pester splat 将值捕获到参数过滤器例程。
代码中的 "bug" 是您使用 $args
作为函数的正常参数,这让 Pester 感到困惑。当 mocked Python
调用时,Pester 看到:
$PSBoundParameters = @{
scriptFile = 'Files\create_db.py'
args = '--DBMS=SQLSERVER -d $database'
}
$args = '--DBMS=SQLSERVER -d $database'
稍后 Pester 调用参数筛选器脚本与此类参数等效:
-scriptFile: 'Files\create_db.py' -args: '--DBMS=SQLSERVER -d $database' '--DBMS=SQLSERVER -d $database'
由于参数过滤器脚本没有定义任何参数,它可以接受位置参数 '--DBMS=SQLSERVER -d $database'
,你得到 ParameterBindingException
.
您可以将此类行为称为 Pester 中的错误。由于高级函数不填充 $args
自动变量,因此不应首先捕获它。 Pester 已经有了不从父范围捕获 $args
的保护,它只需要额外的保护来在模拟高级函数或 cmdlet 时不捕获 $args
。
但是你真的不应该使用 $args
作为普通参数。您最好将参数名称更改为 Arguments
并使用 Args
作为别名:
[Parameter(Position=2)]
[Alias('Args')]
[string]$Arguments
我正在尝试进行一些 Pester 测试,但出现奇怪的错误 "A positional parameter cannot be found"(对于私有 Python cmdlet),这是 Pester 的限制还是我下面的代码有问题?
TestModule.psm1
代码:
#public function:
Function Create-Db
{
[CmdletBinding()]
Param(
[Parameter(Mandatory, ValueFromPipeline)]
[string]$database
)
Python 'Files\create_db.py' '--DBMS=SQLSERVER -d $database'
}
#private (not exported) function:
Function Python
{
[CmdletBinding()]
Param(
[Parameter(Mandatory, Position=1)]
[string]$scriptFile,
[Parameter(Position=2)]
[string]$args
)
$python ='C:\Python27\python.exe'
Push-Location $PSScriptRoot
$python = Start-Process -FilePath $python -ArgumentList @($scriptFile,$args) -Wait -NoNewWindow -PassThru
if($python.ExitCode -ne 0)
{
throw "Python script", $scriptFile, "failed"
}
Pop-Location
}
函数的纠错代码:
$scriptDirectory = (Split-Path -Parent $MyInvocation.MyCommand.Path) -replace "Test$"
Import-Module $scriptDirectory\TestModule.psm1 -Force
Describe "Create-Db test" {
Context "Create database" {
Mock -ModuleName TestModule Python -Verifiable { return; }
Create-Db -database "test_database"
It "Python has been called" {
Assert-VerifiableMocks
}
}
}
当我执行测试代码时出现此错误:
Describing Create-Db test Context Create database [-] Error occurred in Context block 1.35s ParameterBindingException: A positional parameter cannot be found that accepts argument '--DBMS SqlServer -d test_database'. at Test-ParameterFilter, C:\Program Files\WindowsPowerShell\Modules\Pester.3.14\Functions\Mock.ps1: line 1086
$args
是一个自动变量,它包含非高级函数的所有非绑定参数。 Pester 对此进行了解释。当调用模拟命令时,Pester 捕获 $PSBoundParameters
和 $args
作为传递参数的指示。后来 Pester splat 将值捕获到参数过滤器例程。
代码中的 "bug" 是您使用 $args
作为函数的正常参数,这让 Pester 感到困惑。当 mocked Python
调用时,Pester 看到:
$PSBoundParameters = @{
scriptFile = 'Files\create_db.py'
args = '--DBMS=SQLSERVER -d $database'
}
$args = '--DBMS=SQLSERVER -d $database'
稍后 Pester 调用参数筛选器脚本与此类参数等效:
-scriptFile: 'Files\create_db.py' -args: '--DBMS=SQLSERVER -d $database' '--DBMS=SQLSERVER -d $database'
由于参数过滤器脚本没有定义任何参数,它可以接受位置参数 '--DBMS=SQLSERVER -d $database'
,你得到 ParameterBindingException
.
您可以将此类行为称为 Pester 中的错误。由于高级函数不填充 $args
自动变量,因此不应首先捕获它。 Pester 已经有了不从父范围捕获 $args
的保护,它只需要额外的保护来在模拟高级函数或 cmdlet 时不捕获 $args
。
但是你真的不应该使用 $args
作为普通参数。您最好将参数名称更改为 Arguments
并使用 Args
作为别名:
[Parameter(Position=2)]
[Alias('Args')]
[string]$Arguments