为什么Pester不使用两个参数模拟cmdlet?

时间:2016-02-15 09:33:45

标签: powershell pester

我正在尝试进行一些Pester测试,并且我得到奇怪的错误“无法找到位置参数”(对于私有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
}

该函数的Pester代码:

$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.3.14\Functions\Mock.ps1: line 1086

1 个答案:

答案 0 :(得分:4)

$args是一个自动变量,包含非高级函数的所有非约束参数。而且它被Pester解释为。当调用模拟命令时,Pester捕获$PSBoundParameters$args作为传递参数的指示。后来Pester splat将值捕获到参数过滤器例程。

代码中的"错误" 是您使用$args作为您的函数的正常参数,并使Pester混淆。当被嘲笑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