powershellunit-testingerror-handlingpester

How can you mock an ErrorRecord with Pester in Powershell?


I have a function that I would like to include in my unit tests but I'm unable to figure out how. The method takes in an ErrorRecord object (from an Invoke-RestMethod call), grabs the status code and generates a custom error message. Here is what the first portion of the call looks like:

function Resolve-RestError {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $RequestError
    )
    $statusCode = $requestError.Exception.Response.StatusCode.value__
    switch ($statusCode) {

The problem that I am running into is in the recreation of the ErrorRecord object. I have spent many hours looking for a way to recreate the error object, but I am not able to recreate it exactly.

In the actual ErrorRecord object during execution, accessing the Response.StatusCode field returns a string with a description of the code. To access the actual value you need to call Response.StatusCode.value__. It seems that it's not possible to reconstruct an internal .value__ variable as this is done by the JIT compiler (from my understanding). Is there a way to either add a .value__ property to a custom object, or simply mock that variable during my tests?


Solution

  • You're right it doesn't seem overly simple to recreate an ErrorRecord object. My goto for this sort of thing is to simulate the output I want to Mock in my test and then store that result via Export-CliXml but when trying this with an ErrorRecord you only get as far as Exception.Response and the rest is lost in the conversion (even when setting a -Depth value).

    There might be a smarter way, but one workaround would be to just fake the object as follows (note you didn't provide your full Function so I just created a simplified version of it to prove it worked for this specific case):

    function Resolve-RestError {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
            $RequestError
        )
        $statusCode = $RequestError.Exception.Response.StatusCode.value__
    
        Return $statusCode
    }
    
    Describe 'Resolve-RestError' {
    
        It 'Should handle a 404' {
    
            $ErrorRecord = [pscustomobject]@{ 
                Exception = @{
                    Response = @{
                        StatusCode = @{
                            value__ = 404
                        }
                    }
                }
            }
            
            Resolve-RestError -RequestError $ErrorRecord | Should -Be 404
        }
    }