使用Pester测试PowerShell文件筛选函数的两类问题
PowerShell文件清理函数的Pester测试问题解决
先修正原函数的潜在问题
原函数中$fileList未初始化,直接调用AddRange会报错,且类型应该是FileInfo(因为Get-ChildItem -File返回的是文件对象),修正后的函数:
function CheckFilesToDelete([string[]]$fList) { # 初始化泛型列表,类型匹配Get-ChildItem -File的返回结果 [System.Collections.Generic.List[System.IO.FileInfo]]$fileList = [System.Collections.Generic.List[System.IO.FileInfo]]::new() foreach($folderName in $fList) { $path = $folderName # 过滤文件名包含TMP的文件 $list = @(Get-ChildItem $path -File -Recurse | Where-Object { $_.Name -match '.*TMP.*' }) if($list.Count -gt 0) { $fileList.AddRange($list) } } return $fileList }
解决你的两个测试问题
问题1:显示$list查看文件列表
在Pester的It块中,可通过以下方式输出文件列表详情:
# 输出文件的关键属性到控制台 Write-Host "返回的文件列表:" $list | Select-Object Name, CreationTime, FullName | Format-Table | Out-Host
也可以直接用$list | Out-Host快速查看,若断言失败,Pester会自动打印实际返回值,无需手动输出也能排查问题。
问题2:对比$list与$expected
因为$list是文件对象集合,不能直接和字符串数组对比,提供两种可行方案:
方案1:仅对比文件名集合
提取$list的Name属性,和预期文件名数组直接对比:
Describe "Validate files to delete" { Context "When scanning folders for TMP files" { It "should return expected TMP files" { [string[]]$folderList = "Tests" # 预期的文件名数组 $expectedFileNames = @('1_TMP.txt','2_TMP.txt') # Mock Get-ChildItem返回模拟文件对象 Mock Get-ChildItem { [PSCustomObject]@{ Name = '1_TMP.txt' }, [PSCustomObject]@{ Name = 'SmokeTest.txt' }, [PSCustomObject]@{ Name = '2_TMP.txt' }, [PSCustomObject]@{ Name = 'qq02000.doc' } } # 调用函数(注意函数仅接受-fList参数,删除原测试中不存在的-EnvPath) $list = CheckFilesToDelete -fList $folderList -ErrorAction Stop # 输出列表查看(解决问题1) $list | Select-Object Name | Out-Host # 对比文件名(解决问题2) $list.Name | Should -BeExactly $expectedFileNames } } }
方案2:对比完整文件对象属性
若需要验证更多属性(如创建时间、路径),可创建匹配的模拟对象进行全属性对比:
Describe "Validate files to delete" { Context "When scanning folders for TMP files" { It "should return files with correct properties" { [string[]]$folderList = "Tests" # 创建预期的模拟文件对象 $expected = @( [PSCustomObject]@{ Name = '1_TMP.txt' CreationTime = Get-Date '2024-01-01' FullName = "C:\Tests\1_TMP.txt" }, [PSCustomObject]@{ Name = '2_TMP.txt' CreationTime = Get-Date '2024-01-03' FullName = "C:\Tests\2_TMP.txt" } ) Mock Get-ChildItem { [PSCustomObject]@{ Name = '1_TMP.txt' CreationTime = Get-Date '2024-01-01' FullName = "C:\Tests\1_TMP.txt" }, [PSCustomObject]@{ Name = 'SmokeTest.txt' CreationTime = Get-Date '2024-01-02' FullName = "C:\Tests\SmokeTest.txt" }, [PSCustomObject]@{ Name = '2_TMP.txt' CreationTime = Get-Date '2024-01-03' FullName = "C:\Tests\2_TMP.txt" }, [PSCustomObject]@{ Name = 'qq02000.doc' CreationTime = Get-Date '2024-01-04' FullName = "C:\Tests\qq02000.doc" } } $list = CheckFilesToDelete -fList $folderList -ErrorAction Stop # 输出列表详情 $list | Format-List Name, CreationTime, FullName | Out-Host # 全属性对比(-BeEquivalentTo忽略顺序,-BeExactly严格匹配顺序) $list | Should -BeEquivalentTo $expected } } }
额外注意事项
- 原测试代码中调用函数时使用的
-EnvPath $path是无效参数,函数定义中仅存在-fList,必须删除该参数否则会报错。 - Mock的对象建议模拟真实
FileInfo的属性,避免原函数使用其他属性时出现异常。
内容的提问来源于stack exchange,提问作者Enrico
相关产品推荐
相关产品推荐

