Powershell 5类的Pester模拟方法

Ben*_*itM 5 powershell class pester

我在尝试模拟powershell 5类方法时遇到问题,在执行测试时,我收到错误"CommandNotFoundException:找不到Command FunctionToMock".我试图通过模拟"FunctionToMock"来单元测试"OutputToOverwrite"方法.我想我必须首先嘲笑ChocoClass本身,但我不知道该怎么做.谢谢.

Class ChocoClass
{
    [string] OutputToOverwrite()
    {
        return $this.FunctionToMock()
    }

    [string] FunctionToMock()
    {
        return "This text will be replaced"
    }
}


Describe "Testing mocking"{
    it "Mock test"{
        Mock FunctionToMock -MockWith {return "mystring"}
        $package = New-Object ChocoClass
        $expected = $package.OutputToOverwrite()
        $expected | should BeExactly "mystring"
    }
}
Run Code Online (Sandbox Code Playgroud)

alx*_*x9r 6

我见过两种方法可以做到这一点:

  1. 将大部分实现分成一个函数。
  2. 从类继承并重写方法。

(1) 使用函数

我一直将方法的实现分成这样的函数:

Class ChocoClass
{
    [string] OutputToOverwrite()
    {
        return $this.FunctionToMock()
    }

    [string] FunctionToMock()
    {
        return FunctionToMock $this
    }
}

function FunctionToMock
{
    param($Object)
    return "This text will be replaced"
}
Run Code Online (Sandbox Code Playgroud)

完成此更改后,您的测试就在我的计算机上通过了。这避免了与 PowerShell 类相关的陷阱,也避免了测试类行为。

(2) 方法的派生和重写

您可以派生该类并覆盖您想要模拟的方法:

Describe "Testing mocking"{
    it "Mock test"{
        class Mock : ChocoClass {
            [string] FunctionToMock() { return "mystring" }
        }
        $package = New-Object Mock
        $expected = $package.OutputToOverwrite()
        $expected | should BeExactly "mystring"
    }
}
Run Code Online (Sandbox Code Playgroud)

这个测试在我的电脑上通过了。我还没有在生产代码中使用过这种方法,但我喜欢它的直接性。请注意与在单个 PowerShell 会话中重新定义具有相同名称的类相关的问题(请参阅下面的旁注)。


附注:(1) 的分离最大限度地减少了我遇到此错误的次数,该错误会阻止在对类进行更改时重新加载类。不过,我发现更好的解决方法是在新的 PowerShell 会话中调用每个测试运行(例如PS C:\>powershell.exe -Command { Invoke-Pester }),所以我现在倾向于 (2)。