如何在Pester中模拟返回单个哈希表的管道函数?
解决Pester中模拟管道函数返回单个哈希表的问题
问题描述
在Pester中模拟带管道的函数时,原函数逻辑是begin块创建哈希表,process块逐个更新内容,最后end块返回单个哈希表。但直接在Mock里写end块时,发现end块会跟着每个管道项重复执行,导致返回的是哈希表数组,和原函数的行为不一致。
复现问题的代码如下:
BeforeAll { function Get-NameInfo ( [Parameter(ValueFromPipeline = $true, Mandatory = $true)] [string]$FeatureName ) { begin { $result = @{ InputNames = @() InputCount = 0 } } process { $result.InputNames += $FeatureName $result.InputCount++ } end { return $result } } function Get-Result ([array]$ArrayOfNames) { $result = $ArrayOfNames | Get-NameInfo return $result } } Describe 'Get-Result' { BeforeAll { Mock Get-NameInfo { end { return @{ InputNames = @(); InputCount = 0 } } } } BeforeEach { $names = @('Name 1', 'Name 2', 'Name 3', 'Name 4') } It 'doesn''t return an array' { $result = Get-Result $names # 报错:Expected $false, but got $true. $result -is [System.Object[]] | Should -BeFalse } }
解决方案
问题根源是Pester对Mock脚本块的解析逻辑:如果只在Mock里写end块,Pester会把它当成每个管道项都会执行的逻辑,而非真正的管道生命周期end块。要模拟正确的管道行为,必须在Mock中完整定义begin、process、end三个块,让Pester识别这是一个管道函数的模拟。
修改后的Mock代码:
Mock Get-NameInfo { begin { # 初始化哈希表,只在管道启动时执行一次 $mockResult = @{ InputNames = @(); InputCount = 0 } } process { # 可选:如果需要模拟process块的更新逻辑,在这里处理每个管道项 # $mockResult.InputNames += $FeatureName # $mockResult.InputCount++ } end { # 仅在所有管道项处理完成后执行一次,返回单个哈希表 return $mockResult } }
核心要点
- 必须完整定义三个块:只有显式写出
begin、process、end,Pester才会按照管道函数的生命周期执行,确保end块只运行一次。 - 状态初始化放在
begin块:哈希表在begin块创建,保证全局唯一,不会被每个管道项重新初始化。 process块可留空:如果不需要模拟具体的更新逻辑,process块可以是空的,但不能省略,否则Pester会默认把脚本块内容当作process逻辑重复执行。
修改后运行测试,Get-Result会返回单个哈希表,断言$result -is [System.Object[]] | Should -BeFalse会通过。
内容的提问来源于stack exchange,提问作者Simon Elms
相关产品推荐
相关产品推荐

