nohwnd / Assert

A set of advanced assertions for Pester to simplify how you write tests.
MIT License
101 stars 12 forks source link

Using Assert-Throw to Test Terminating vs Non-Terminating Errors #32

Open pldmgg opened 6 years ago

pldmgg commented 6 years ago

Hi there -

I'm relatively new to Pester (and consequently, new to your Module), but I had a question about how Assert-Throw is supposed to work.

I've got a PowerShell Module called TheThing.psm1 with the following functions:

function GetElevation {
    if ($PSVersionTable.PSEdition -eq "Desktop" -or $PSVersionTable.Platform -eq "Win32NT" -or $PSVersionTable.PSVersion.Major -le 5) {
        [System.Security.Principal.WindowsPrincipal]$currentPrincipal = New-Object System.Security.Principal.WindowsPrincipal(
            [System.Security.Principal.WindowsIdentity]::GetCurrent()
        )

        [System.Security.Principal.WindowsBuiltInRole]$administratorsRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator

        if($currentPrincipal.IsInRole($administratorsRole)) {
            return $true
        }
        else {
            return $false
        }
    }

    if ($PSVersionTable.Platform -eq "Unix") {
        if ($(whoami) -eq "root") {
            return $true
        }
        else {
            return $false
        }
    }
}

function Do-Thing {
    [CmdletBinding()]
    Param()

    if (!$(GetElevation)) {
        Write-Error "The $(MyInvocation.MyCommand.Name) function must be run from an elevated PowerShell Session (i.e. 'Run As Administrator')! Halting!"
        $global:FunctionResult = "1"
        return
    }
}

...and I setup my Pester Test like...

Import-Module "$PSScriptRoot\TheThing.psm1"

InModuleScope TheThing {
    Describe "Test Do-Thing function" {
        Context "Elevated PowerShell Session" {
            Mock 'GetElevation' -MockWith {$True}

            # Passes
            It "Should Throw A Non-Terminating Error" {
                Do-Thing | Assert-Throw -ScriptBlock
            }

            # Passes
            It "Should Throw A Terminating Error Using '-ErrorAction Stop'" {
                Do-Thing -ErrorAction Stop | Assert-Throw
            }

            # Passes
            It "Should Throw A Non-Terminating Error Take 2" {
                Do-Thing | Assert-Throw -AllowNonTerminatingError
            }

            # Passes
            It "Should Throw A Terminating Error Using '-ErrorAction Stop' Take 2" {
                Do-Thing -ErrorAction Stop | Assert-Throw -AllowNonTerminatingError
            }
        }
    }
}

If I place all of the 'Do-Thing' function calls into a scriptblocks (i.e. {Do-Thing} | Assert-Throw etc.) like I've seen in some examples floating around, they all fail.

Basically all I'm looking to do is test that a terminating error is thrown when -ErrorAction Stop is used and a non-terminating error is thrown when -ErrorAction Stop is NOT used.

Thoughts?

matt2005 commented 6 years ago

Here is a sample of how i understand it, The errorActionPreference is handled inside the Assert-throw so you don't need to include it.

Describe -Name 'Assert-Throw with Specific message' -Fixture {
    It -name 'With AllowNonTerminatingError and specific Error Message and Throw' -test {
    # This should fail due to the Write-Error being a non-terminating error and being skipped due to the -AllowNonTerminatingError Switch
        {
            Write-Error ('This should Error')
            Throw ('Error Thrown')
        } | Assert-Throw -AllowNonTerminatingError -ExceptionMessage ('This should Error') 
    }
    It -name 'Without AllowNonTerminatingError and specific Error Message' -test {
        {
            Write-Error ('This should Error')
            Throw ('Error Thrown')
        } | Assert-Throw -ExceptionMessage ('This should Error')
    }
    It -name 'With AllowNonTerminatingError and specific Error Message and Throw' -test {
    # This should pass
        {
            Write-Error ('This should Error')
            Throw ('Error Thrown')
        } | Assert-Throw -AllowNonTerminatingError -ExceptionMessage ('Error Thrown')
    }
    It -name 'Without AllowNonTerminatingError and specific Error Message' -test {
    # This should fail because the message expected is the throw message but the error message produced
        {
            Write-Error ('This should Error')
            Throw ('Error Thrown')
        } | Assert-Throw -ExceptionMessage ('Error Thrown')
    }
}