如何在PowerShell类方法中Mock Get-Content cmdlet?
如何Mock PowerShell类方法中调用的Cmdlet
你遇到的问题根源在于:PowerShell类的方法运行在独立的模块作用域内,Pester默认的Mock只会作用于测试脚本自身的作用域,所以类方法里的Get-Content调用不会被Mock拦截,依然会执行真实命令。
下面提供两种可行的解决方案:
方案一:指定Mock的目标模块
如果你的类定义在脚本模块(.psm1)里,在Mock时通过-ModuleName参数指定模块名称,让Mock作用于该模块的作用域,这样类方法里的Cmdlet调用就会被拦截。
修改后的测试代码:
using module .\test.psm1 Describe "MyClass" { BeforeAll { $objClass = [MyClass]::new() # 指定类所在的模块名称(此处模块名为test,对应test.psm1文件) Mock Get-Content -ModuleName test { return "this-is-a-test" } $objClass.GetFileContent("c:\temp\myfile.txt") } It "Should update class variable" { $objClass.filecontent | Should -be "this-is-a-test" } AfterAll { Remove-Variable objClass } }
注意:模块名称为脚本模块文件名去掉扩展名的部分;如果模块有对应的.psd1清单文件,需使用清单中定义的正式模块名。
方案二:重构类为测试友好型
如果希望类的测试更灵活,推荐把外部依赖(比如Get-Content)封装成可注入的委托,无需依赖模块作用域Mock,直接替换依赖即可。
重构后的类文件(test.psm1):
class MyClass { [string]$filecontent # 定义可注入的委托,用于获取文件内容 [Func[string, string]]$ContentGetter = { param($path) Get-Content -Path $path -raw }.GetNewClosure() MyClass() {} [void] GetFileContent([string]$filepath) { $this.filecontent = $this.ContentGetter.Invoke($filepath) } }
对应的测试代码:
using module .\test.psm1 Describe "MyClass" { BeforeAll { $objClass = [MyClass]::new() # 替换委托为Mock实现 $objClass.ContentGetter = { param($path) return "this-is-a-test" }.GetNewClosure() $objClass.GetFileContent("c:\temp\myfile.txt") } It "Should update class variable" { $objClass.filecontent | Should -be "this-is-a-test" } AfterAll { Remove-Variable objClass } }
这种方式遵循依赖注入思想,既降低了类的耦合度,也让测试逻辑更清晰。
内容的提问来源于stack exchange,提问作者MVogwell
相关产品推荐
相关产品推荐

