So if you know me you know I like testing, and that when it comes to testing in PowerShell the de-facto testing framework to use is Pester. And it’s claim that it is ubiquitous can be backed-up by the fact that it is now packaged in PowerShell.

One of the great things about Pester is that you can mock a function; that is, if you call a function within another function you can mock the internal funciton. The benefits is threefold: 1) the results are deterministic 2) It reduces the effort in getting a test up and running 3) it also allows you to focus your testing on the function that you are testing.

Sounds great, right? And the great thing about it is that you can even mock exceptions. And this is useful because I have a function that needs to know the status of a web request to an API in order to do one thing or another. I’m using azure.databricks.cicd.tools to determine if a notebook or folder has been deleted on the workspace, and if it has then delete the item locally. Here is a snippet -

        Try {
            Get-DatabricksWorkspaceFolder -Path $WorkspaceFolder | Out-Null
        Catch {     
            if ($_.Exception.Response.StatusCode -eq "Forbidden") {
                Write-Error $_.Exception.Response
            elseif ($_.Exception.Response.StatusCode -eq "NotFound") {
                Write-Verbose "Folder $WorkspaceFolder not found in workspace. Deleting locally."
                Remove-Item $object.FullName -Force -Recurse
                $results.RemovedFolders = $results.RemovedFolders + 1

I’m checking for a 403 “FORBIDDEN” so that I do not accidentally delete a load of notebooks locally. It’s all source controlled so even if it did it would be recoverable, but better to have this check in place for sure!

So in my test I need to mock an exception of type “HttpResponseException”, and call either a 403 or a 404 in order to do one thing or another -

Mock "Get-DatabricksWorkspaceFolder" {
            $errorDetails = '{"code": 1, "message": "NotFound", "more_info": "", "status": 404}'
            $statusCode = 404
            $response = New-Object System.Net.Http.HttpResponseMessage $statusCode
            $exception = New-Object Microsoft.PowerShell.Commands.HttpResponseException "$statusCode ($($response.ReasonPhrase))", $response
            $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation
            $errorID = 'WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
            $targetObject = $null
            $errorRecord = New-Object Management.Automation.ErrorRecord $exception, $errorID, $errorCategory, $targetObject
            $errorRecord.ErrorDetails = $errorDetails
            Throw $errorRecord

At this point, when I run my test the function Get-DatabricksWorkspaceFolder will execute this piece of code above. And whilst this is a bit of effort to create a legitimate execption to mock a call to an API, it is infinitely easier to do this than to set up a databricks workspace, handle a bearertoken etc etc.

$testConfig = [PSCustomObject]@{
            dataBricksPath = '/Users/[email protected]/project/'
        $localPath = Join-Path $PSScriptRoot "project"
        New-Item -Path $PSScriptRoot/project/module -ItemType Directory -Force
        New-Item -Path $PSScriptRoot/project/test.py -ItemType File -Force
        $output = Remove-LocalNotebooks -localPath $localPath -config $testConfig -Verbose
        $output.RemovedFolders | Should Be 1
        $output.RemovedNotebooks | Should Be 1
        Remove-Item -Path $PSScriptRoot/project -Force

So with mocking I can mock the different statuses quite easily.