如何在Pester中模拟带有强制参数的PowerShell函数
如何在Pester中模拟带强制参数的PowerShell函数?
首先,咱们先理清需求:你有一个带强制参数的PowerShell函数Verify_AuthenticodeSignature,想要用Pester测试它,同时还要模拟它依赖的外部命令(比如Test-Path、Get-AuthenticodeSignature)——如果这些依赖本身也带强制参数,也能轻松处理。下面一步步来:
第一步:调整被测脚本,方便测试
你的原Testcase.ps1最后直接调用了Verify_AuthenticodeSignature,但没传参数,运行会报错,而且在Pester中导入脚本时会自动执行这个调用,干扰测试。咱们给它加个判断,只有当脚本直接运行时才执行函数:
# Testcase.ps1 修改后 function Verify_AuthenticodeSignature{ Param( [Parameter(Mandatory=$true)] [string]$PSFilePath ) Write-Host $PSFilePath if (-Not (Test-Path $PSFilePath)){ Write-Output "file does not exist" exit 1 } $Status=(Get-AuthenticodeSignature -FilePath $PSFilePath).Status if($Status -ne "Valid"){ Write-Output "Script is not signed" } } # 仅当脚本直接运行时调用函数(测试时导入脚本不会触发) if ($MyInvocation.MyCommand.Path -eq $PSCommandPath) { Verify_AuthenticodeSignature }
第二步:编写Pester测试,模拟依赖函数
现在咱们来写Testcase.Tests.ps1,核心是用Pester的Mock命令来模拟依赖的函数,哪怕这些依赖本身带有强制参数,也能轻松处理:
# Testcase.Tests.ps1 $here = Split-Path -Parent $MyInvocation.MyCommand.Path $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace('.Tests.ps1', '.ps1') . "$here\$sut" Describe "Verify_AuthenticodeSignature" { Context "When the target file does not exist" { BeforeAll { # 模拟Test-Path返回$false,哪怕它有参数要求 Mock Test-Path { return $false } -ParameterFilter { $Path -eq "C:\fake\script.ps1" } } It "Outputs 'file does not exist' and exits with code 1" { # 因为函数会exit,所以用&调用捕获退出码 $output = & { Verify_AuthenticodeSignature -PSFilePath "C:\fake\script.ps1" } 2>&1 $LASTEXITCODE | Should -Be 1 $output | Should -Contain "file does not exist" # 验证Test-Path被调用了一次 Assert-MockCalled Test-Path -Exactly 1 } } Context "When the file exists but signature is invalid" { BeforeAll { Mock Test-Path { return $true } -ParameterFilter { $Path -eq "C:\valid\script.ps1" } # 模拟Get-AuthenticodeSignature返回无效签名状态,它的-FilePath是强制参数,Mock会自动处理 Mock Get-AuthenticodeSignature { return [PSCustomObject]@{ Status = "Invalid" } } -ParameterFilter { $FilePath -eq "C:\valid\script.ps1" } } It "Outputs 'Script is not signed'" { $output = Verify_AuthenticodeSignature -PSFilePath "C:\valid\script.ps1" $output | Should -Contain "Script is not signed" Assert-MockCalled Get-AuthenticodeSignature -Exactly 1 } } Context "When the file exists and signature is valid" { BeforeAll { Mock Test-Path { return $true } -ParameterFilter { $Path -eq "C:\signed\script.ps1" } Mock Get-AuthenticodeSignature { return [PSCustomObject]@{ Status = "Valid" } } -ParameterFilter { $FilePath -eq "C:\signed\script.ps1" } } It "Does not output any error messages" { $output = Verify_AuthenticodeSignature -PSFilePath "C:\signed\script.ps1" $output | Should -BeNullOrEmpty Assert-MockCalled Get-AuthenticodeSignature -Exactly 1 } } }
关键知识点:模拟带强制参数的函数
如果要模拟的函数本身带有强制参数(比如Get-AuthenticodeSignature的-FilePath是强制的),Pester的Mock命令完全能处理:
- 你不需要额外处理强制参数,只要在
-ParameterFilter里指定参数值,Mock就会匹配对应的调用 - 如果需要让Mock接受任何强制参数值,可以省略
-ParameterFilter,或者用{ $FilePath }这样的简单过滤条件 - 要是你想模拟函数的参数校验(比如测试当没传强制参数时的行为),可以直接调用函数不传参数,Pester会捕获对应的错误:
It "Throws an error when PSFilePath is not provided" { { Verify_AuthenticodeSignature } | Should -Throw "Parameter set cannot be resolved" }
运行测试
打开PowerShell,切换到脚本所在目录,运行:
Invoke-Pester -Path .\Testcase.Tests.ps1
这样就能看到所有测试用例的执行结果啦!
内容的提问来源于stack exchange,提问作者Sakshi Rawal
相关产品推荐
相关产品推荐

