问题
I am having an issue trying to mock a powershell 5 class method, when executing the test, I get the error " CommandNotFoundException: Could not find Command FunctionToMock". I am trying to unit test the "OutputToOverwrite" method by mocking "FunctionToMock". I think I would have to mock ChocoClass itself first, but I am not sure how to do it. Thanks.
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"
}
}
回答1:
I have seen two ways to do this:
- Separate the bulk of the implementation into a function.
- Inherit from the class and override the method.
(1) Use a Function
I have been separating the implementation of methods into functions like this:
Class ChocoClass
{
[string] OutputToOverwrite()
{
return $this.FunctionToMock()
}
[string] FunctionToMock()
{
return FunctionToMock $this
}
}
function FunctionToMock
{
param($Object)
return "This text will be replaced"
}
With that change, your test passes on my computer. This avoids PowerShell-class-related pitfalls but also avoids testing class behavior.
(2) Derive and Override the Method
You can derive the class and override the method you want to mock:
Describe "Testing mocking"{
it "Mock test"{
class Mock : ChocoClass {
[string] FunctionToMock() { return "mystring" }
}
$package = New-Object Mock
$expected = $package.OutputToOverwrite()
$expected | should BeExactly "mystring"
}
}
This test passes on my computer. I haven't used this method for production code yet, but I like how direct it is. Watch out for problems related to re-defining classes with the same name in a single PowerShell session (see side note below).
Side note: The separation of (1) minimizes the amount I run into this bug that prevents classes from being reloaded when you make changes to them. I have found, though, that the better workaround is to invoke each test run in a new PowerShell session (e.g. PS C:\>powershell.exe -Command { Invoke-Pester }
) so I'm leaning toward (2) now.
来源:https://stackoverflow.com/questions/42513644/pester-mock-method-for-powershell-5-class