-
Notifications
You must be signed in to change notification settings - Fork 3
Mocking a Command
First, make sure you have imported the PSMock module and enabled mocking in your script:
Import-Module PSMock
Enable-Mock | iex
function Hello { param ([string] $who) "Hello, $who" }
To mock a function, just call Mock with the function name and a replacement scriptblock. The mock will be called instead of your function.
Mock Hello { "Good morning" }
Hello bob # "Good morning"
PSMock is smart enough to add the parameters to your With and When clauses automatically. The parameters will match the parameters of the original function or command.
Mock Hello { "Good day, $who" }
Hello bob # "Good day, bob"
If you don't specify a With block, a mock will do nothing:
Mock Hello
Hello bob # nothing
PSMock allows you to mock a function that doesn't exist. Generally you would only do this to avoid having to include the script that defines a function. You can create the mock, but PSMock won't know what the parameters are for the function. You will have to do it yourself.
Mock NotAFunction { "Return $args[0]" }
NotAFunction 'foo' # "Return foo"
Better yet, add a param clause, and the parameters get mapped automatically.
Mock NotAFunction { param ([string] $Path) "Return $Path" }
NotAFunction 'foo' # "Return foo"
PSMock uses aliases to intercept calls to functions and commands, so it's not able to mock aliases. But you should be mocking the underlying command anyway, and that's what PSMock will try to do if you try to mock an alias.
Mock ls
# this will throw an exception
So let's say you have an original function:
function Original { "original" }
Original # "original"
You can mock it with the Mock command. In this case, we will override all calls to Original:
Mock Original { "mocked" }
Original # "mocked"
We can also remove the mock:
Remove-Mock Original
Original # "original"
Sometimes you want different code to execute depending on the parameters. You can use the When parameter to filter the execution:
function Hello { param ([string] $who) "Hello, $who" }
Hello you # "Hello, you"
Mock Hello { } -when { $who -eq "Bob" }
Hello you # "Hello, you"
Hello bob # nothing
Mock Hello { "Good day, $who" }
Hello bob # nothing
Hello you # "Good day, you"
Remove-Mock Hello
Hello bob # "Hello, bob"
Hello you # "Hello, you"
If you are using mocks for testing, you may want to look at the statistics that PSMock keeps for the mocks:
Mock Hello { } -when { $who -eq "Bob" } -name Bob
Mock Hello { "Good day, $who" }
Hello bob # nothing
Hello you # "Good day, you"
(Get-Mock Hello).Count # 2
(Get-Mock Hello -case Bob).Count # 1
(Get-Mock Hello -case default).Count # 1
(Get-Mock Hello -case default).Calls[0].BoundParameters['who'] # "you"
You can also use MockContexts to automatically remove certain sets of mocks. This is very handy for more complicated test scenarios. You can even nest MockContexts.
MockContext {
Mock Hello { } -when { $who -eq "Bob" } -name Bob
Hello bob # nothing
}
Hello bob # "Hello, bob"