Unit Testing with Pester, Mocking Problem


This topic contains 6 replies, has 2 voices, and was last updated by  Robbie Courtney 2 years, 1 month ago.

  • Author
  • #28452

    Robbie Courtney

    I've been playing around with pester for a few weeks and have had some success but have run into a few hurdles.

    One hurdle seems to be how mocking works. I have a simple example below. There is really no purpose for this test except to act as an example of problems that I am running into.


    function PesterTest {
        $path = Get-Content '.\somepath.txt'
        if (Test-Path $path){
            "file does exist"
        else {
            "file does not exist"


    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
    . "$here\$sut"
    Describe "PesterTest" {
        Context "Path does exist" {
            Mock Get-Content {}
            Mock Test-Path {$true}
            It "Test-Path is valid" {
                PesterTest | should be "file does exist"

    When I run invoke-pester the test fail because I get an error “Cannot bind argument to parameter 'Path' because it is null.”

    From my understanding Get-Content should return nothing because it is mocked, making the $path variable null. I would not think that this matters because Test-Path is mocked to return $true and it should not matter that the parameter that is passed is null via the $path variable. This assumption is not the case and I don't understand why.

    Now I can make Get-Content output some [String] data by mocking it like this

    Mock Get-Content {“some content”}, the reason that this works from what I can tell is because Test-Path -Path parameter wants a string. If I mock Get-Content to return a string then it works.

    This is a simple work around for this test but for other cmdlets that want an say a ADObject or a [Microsoft.Windows.ServerBackup.Commands.WBPolicy] object such as the Add-WBBackupTarget -Policy parameter this doesn't work there is no easy way to mock that.

    I would think if I mocked the Test-Path command to give an output of $true then it shouldn't matter if in the actual function Test-Path gets passed a parameter of -Path that is null because of the previous mock of Get-Content {}.

    If anyone has some Ideas, or suggestions I would appreciate it. If needed, I could post some more examples. I wanted to keep it simple, and came up with this test scenario.

    Any help would be great, thanks!

  • #28466

    Dave Wyatt

    When you mock a command with Pester, the mock automatically inherits all of the parameter metadata of the original command (including things like Mandatory and ValidateNotNullOrEmpty), so you still need to make sure your calls to the mock are legal.

    In this case, just make your Get-Content mock return some non-empty string, and you should be fine:

    Mock Get-Content { return 'Anything can go here' }
  • #28497

    Robbie Courtney

    Thanks for your response.

    The answer you gave does solve the example that I have given, but let me give you another example.

    The example of Get-Content to retrieve a String path to pass to Test-Path -Path parameter, probably wasn't the best example because it was easy to mock Get-Content to return a string and make everything happy.

    This is a current problem that I am having in pester testing a script that does a windows backup.

    Part of the Function that I am trying to Mock out

    $policy = New-WBPolicy
    $target = New-WBBackupTarget -NetworkPath $NetworkPath
     Add-WBBackupTarget -Policy $policy -Target $target

    Pester Test Mocking Part

    Mock New-WBPolicy {}
    Mock New-WBBackupTarget {}
    Mock Add-WBBackupTarget {Write-Error "Add-WBBackupTarget error"}

    Error Message :Expected: the expression to throw an exception with message {New-WBBackupTarget error}, an exception was raised, message was {Cannot validate argument on parameter 'Policy'. The argument is null or empty. Sup
    ply an argument that is not null or empty and then try the command again

    The problem here is the same as my previous example, however I cannot figure out how to make the mock command return the right object that Add-WBBackupTarget expects for the two parameters -Policy and -Target.

    The cmdlet expects these two types of objects. Is there an easy way to mock around this?

  • #28499

    Dave Wyatt

    When you run New-WBPolicy and New-WBBackupTarget, do those commands actually modify the system, or just create an object for you to use in memory? If it's the latter, then I wouldn't bother mocking those commands at all; I'd just let those objects get created, and pass them on to my mocked Add-WBBackupTarget command.

    If they actually make changes to the system, then we'd need to come up with something else.

  • #28501

    Robbie Courtney

    It just creates those objects in memory, so I guess it doesn't matter. I'll just not mock those commands.

    One of the reasons I wanted to mock them is to be able to run pester test from a box that did not have the Server Backup windows feature installed, i figured if I mocked those CmdLets out then I could run pester test from other machines such as the new TeamCity community build server. I don't think this will be possible if I cannot mock these commands.

  • #28502

    Dave Wyatt

    That's a tricky point with Pester at the moment, and something that people have been asking about. Right now, in order to use the Mock command, you _have_ to have the original command available (because mocking relies on the original command to figure out its parameters / metadata).

    However, you could just define empty functions with the same names, and then mock those functions (assuming you want Assert-MockCalled functionality. If you don't need that, you don't need to bother mocking the already-empty function.)

  • #28504

    Robbie Courtney

    Ahh ok light bulbs are going off now. That makes everything much more clear.

    Defining empty functions would be a good workaround for what I'm trying to accomplish.

    Thanks again Dave!

You must be logged in to reply to this topic.