Skip to content
Jon Wagner edited this page Feb 8, 2013 · 1 revision

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" }

Mocking Functions and Commands

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"

Mocking Parameters

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"

Empty Mocks

If you don't specify a With block, a mock will do nothing:

Mock Hello
Hello bob						# nothing

Mocking a Function that Doesn't Exist

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"

Mocking Aliases

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"