如何使用Pester v5验证PowerShell Mock函数的传入参数值
Pester v5 如何校验Mock函数接收的参数是否正确
问题描述
我用PowerShell编写了一个函数,正尝试使用Pester v5对其进行测试,下方代码示例包含了待测函数与对应的Pester测试用例。
我想要验证传入被Mock的函数Save-Report的参数$FileName是否正确,请问该如何实现?
注意事项
- 我清楚Mock函数
Add-StringToFileName时会返回测试值来设置$Filename参数,但我仍需要测试该值能完整传递到最终调用环节且未被修改。 - 这类校验逻辑我后续测试也会频繁用到,因此想要了解具体的实现方案。
待测函数
Function Invoke-ReportDownloader { [CmdletBinding()] Param ( # 用于连接数据库的命令对象 [Parameter(Mandatory)] [System.Data.Odbc.OdbcCommand]$Command, # 包含待获取报表项的XML元素 [Parameter(Mandatory)] [System.Xml.XmlElement]$ReportItem, # 包含配置参数的哈希表 [Parameter(Mandatory)] [hashtable]$ConfigParams, # 报表对应的SEMO参与者对象 [Parameter(Mandatory)] [System.Data.DataRow]$Participant ) # 报表不支持则跳过 $ReportName = $ReportItem.ReportName if (-not (Test-ReportSupported $Command $ReportName)) { $Logger.Warning("Report: $($ReportName) is not currently supported") return } # (Kanban-7940) 如果报表项配置的文件名不含时间戳,自动追加对应日期,避免同类型报表覆盖 $Filename = $ReportItem.FileName if (-not (Test-TimestampIncluded -Filename $Filename)) { $FileName = Add-StringToFileName -Path $Filename -SubString $ReportItem.Date } # 数据库已存在该报表则跳过 if (Test-MarketReportInDatabase $Command $ReportItem) { return } Get-Report $ConfigParams $Participant $ReportItem # 响应包含失败信息则抛出异常 $ReportSuccessParams = @{ ResponsePath = $ConfigParams.BmResponsePath BaseName = $ConfigParams.ReportFilter } if (-not (Test-SuccessfulResponse @ReportSuccessParams)) { throw "Unsuccessful response from BM" } $SaveReportParams = @{ RawPath = $ConfigParams.RawPath XmlResponsePath = $ConfigParams.XmlResponsePath Filename = $FileName } Save-Report @SaveReportParams }
现有单元测试代码
Describe 'Invoke-ReportDownloader' { BeforeAll { # 初始化测试用$Cmd对象 # 初始化测试用$Logger对象 # 初始化测试用$ReportItem对象 # 初始化测试用$ConfigParams对象 } Context "文件名不含时间戳场景" { BeforeAll { Mock Test-ReportSupported { return $true } Mock Test-MarketReportInDatabase { return $false } Mock Get-Report Mock Test-SuccessfulResponse { return $true } Mock Save-Report } BeforeEach { $Script:ReportDownloaderParams = @{ Command = $Script:Cmd ReportItem = $ReportItem ConfigParams = $Script:ConfigParams Participant = $Script:Participant } } It "应该将带时间戳的文件名传入保存方法" { $TestFileName = "test_string_20210101" Mock Add-StringToFileName { return $TestFileName } Invoke-ReportDownloader @Script:ReportDownloaderParams Should -InvokeVerifiable Save-Report # 此处需要校验传入Save-Report的$FileName参数是否正确 } } }
解决方案
你可以通过以下3种常用方案实现参数校验,覆盖不同的使用场景:
方案1:使用Should -Invoke的-ParameterFilter参数(最常用)
这是Pester原生支持的参数校验方式,无需额外封装,直接在It块的注释位置替换为以下代码即可:
# 校验Save-Report刚好被调用1次,且传入的Filename参数等于预设的测试值 Should -Invoke Save-Report -ParameterFilter { $Filename -eq $TestFileName } -Exactly 1 -Scope It
你可以在-ParameterFilter的脚本块中写任意匹配逻辑,比如校验文件名格式、包含特定字符串等,灵活度很高。
方案2:封装参数过滤规则到Mock定义(适合高频复用场景)
如果后续大量测试用例都需要校验Save-Report的Filename参数,可以把校验逻辑直接封装到Mock定义中,标记为可验证,后续只需调用Should -InvokeVerifiable即可完成校验:
# 在Context的BeforeAll中定义带参数过滤的可验证Mock Mock Save-Report -Verifiable -ParameterFilter { $Filename -eq $expectedFileName }
不同测试用例可以根据需要重写Mock的参数过滤规则,匹配不同的期望文件名。
方案3:获取Mock调用历史做自定义断言(适合复杂校验场景)
如果需要对参数做更复杂的校验(比如拆分文件名检查日期格式、校验后缀等),可以通过Get-MockCallHistory获取所有调用的参数列表,单独做断言:
# 执行完待测函数后添加以下代码 $saveReportCalls = Get-MockCallHistory -CommandName Save-Report # 校验调用次数 $saveReportCalls.Count | Should -Be 1 # 校验Filename参数值 $saveReportCalls[0].Arguments.Filename | Should -Be $TestFileName # 还可以扩展更多自定义校验逻辑
内容的提问来源于stack exchange,提问作者gerard
相关产品推荐
相关产品推荐

