Be sure to check out the Pester Book for just about everything you need to know out testing PowerShell code with Pester!

One of the many benefits of testing is that it forces best practices. Testing forces you to write more modular, testable code. Here's a great example:

I was writing a test for a function that called another function that returned a non-terminating error if something could not be found. I needed to account for this. Here's the gist of the function:

function Test-Thing {
    param($Name)

    Get-OtherThing -Name $Name
}

When Get-OtherThing couldn't find $Name it returned a non-terminating error that had the string "was not found" inside of it.

I needed my Teat-Thing function to just return $true or $false. To do this, I had to capture the non-terminating error that was returned from Get-OtherThing. The only way to do this (I thought) was to silence the error and capture it using ErrorAction and ErrorVariable.

Get-OtherThing -Name $Name -ErrorAction SilentlyContinue -ErrorVariable err
if ($err -and $err.Exception.Message -match 'was not found') {
    $false
} elseif ($err -and $err.Exception.Message -notmatch 'was not found') {
    throw $err
} else {
    $true
}

This worked fine until I began to write a unit test for it. I couldn't figure out how to properly mock the ErrorVariable. After some thinking about it, I came up with a better solution. Why not just set $ErrorActionPreference to Stop which would make all non-terminating errors to be terminating errors. I could then use a try/catch block. The function then turned into this:

try {
    Get-OtherThing -Name $Name -ErrorAction SilentlyContinue -ErrorVariable err
    $true
} catch {
    if ($_.Exception.Message -match 'was not found') {
        $false
    } else {
        throw $_
    }
}

Now that my function was using try/catch I could now mock Get-OtherThing to throw exceptions rather than figuring out how to account for non-terminating errors!

mock 'Get-OtherThing' {
    throw 'was not found'
}

mock 'Get-OtherThing' {
    throw 'some other error not accounted for'
}

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!