pester / Pester

Pester is the ubiquitous test and mock framework for PowerShell.
https://pester.dev/
Other
3.11k stars 473 forks source link

Enhance `Should -Throw` Documentation with Error Scenario #2064

Closed aolszowka closed 1 year ago

aolszowka commented 3 years ago

Location

https://pester.dev/docs/v4/usage/assertions#throw

General summary of the issue

The documentation is actually very good for Should -Throw however being so new to Pester this threw me for a loop:

function Test-It {
    [CmdletBinding()]
    param()
    process {
        try {
            New-PSSession -ComputerName 'badcomputername687894' -ErrorAction:Stop
            Write-Host -Object "But I continue execution"
        }
        finally {
            Write-Host -Object "This is in the finally block"
        }
    }
}
Import-Module 'Pester'
Describe 'Pester' {
    # This doesn't work like you think it would
    Context 'Context' {
        # Arrange
        Mock New-PSSession { throw 'New-PSSession Throws'}
        Mock Write-Host { }
        # Act
        Test-It
        # Assert
        It 'Should write just finally' {
            Assert-MockCalled -CommandName Write-Host -Times 1 -Exactly -ExclusiveFilter { $Object -eq "This is in the finally block" }
        }
    }
}

This returns an error message similar to the following:

Describing Pester

  Context Context
    [-] Error occurred in Context block 0ms
      RuntimeException: New-PSSession Throws
      at ExecuteBlock, C:\Program Files\WindowsPowerShell\Modules\Pester\4.10.1\Functions\Mock.ps1: line 1215
      at Invoke-Mock, C:\Program Files\WindowsPowerShell\Modules\Pester\4.10.1\Functions\Mock.ps1: line 1025
      at <ScriptBlock><Process>, <No file>: line 172
      at Test-It<Process>, S:\Git\OneOffScripts\Test-It.ps1: line 8
      at <ScriptBlock>, S:\Git\OneOffScripts\Test-It.ps1: line 24
      at DescribeImpl, C:\Program Files\WindowsPowerShell\Modules\Pester\4.10.1\Functions\Describe.ps1: line 213

The problem is a misunderstanding on my part that you MUST put any throwing operation in braces: { } this is actually called out in this StackOverflow post from @markwragg https://stackoverflow.com/a/45574334/433069

The following works:

Import-Module 'Pester'
Describe 'Pester' {
    Context 'Context' {
        # Arrange
        Mock New-PSSession { throw 'New-PSSession Throws'}
        Mock Write-Host { }
        # Act/Assert
        It 'Should write just finally' {
            { Test-It -ErrorAction:Stop } | Should -Throw -ExpectedMessage 'New-PSSession Throws'
            Assert-MockCalled -CommandName Write-Host -Times 1 -Exactly -ExclusiveFilter { $Object -eq "This is in the finally block" }
        }
    }
}

I am not sure how best the documentation could be improved, I think perhaps having the error message that occurs if you do it "wrong" might be helpful. In some ways the documentation tries to call this out with this blurb: Warning: The input object must be a ScriptBlock, otherwise it is processed outside of the assertion. The hope is that someone else encountering this will run across this issue eventually.

fflaten commented 1 year ago

Thanks for the report and sorry for the late response.

There won't be any change to this regarding Pester v4. I have just submitted a PR for Pester v5 to improve the error when using Should -Throw without providing a scriptblock as input as it was currently not working as intended. See #2354 for before and after examples.

Your initial sample doesn't use Should -Throw at all, so I don't think we can improve that. Exceptions in It-blocks are also used by custom assertions (not Should) so would be hard to distinguish mistakes from intentional exceptions to provide a hint in Diagnostic-logs.