You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:29:35