diff --git a/Assert.psd1 b/Assert.psd1 index 46158e4..23c2a91 100644 --- a/Assert.psd1 +++ b/Assert.psd1 @@ -86,6 +86,7 @@ FunctionsToExport = @( 'Assert-NotLike' 'Assert-StringEqual' 'Assert-StringNotEqual' + 'Get-ChildException' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. diff --git a/Assert.psm1 b/Assert.psm1 index 782ca7e..4ac61c4 100644 --- a/Assert.psm1 +++ b/Assert.psm1 @@ -31,4 +31,5 @@ Export-ModuleMember -Function @( 'Assert-NotLike' 'Assert-StringEqual' 'Assert-StringNotEqual' + 'Get-ChildException' ) \ No newline at end of file diff --git a/src/Exception/Assert-Throw.ps1 b/src/Exception/Assert-Throw.ps1 index d7fa1c3..c1f13d6 100644 --- a/src/Exception/Assert-Throw.ps1 +++ b/src/Exception/Assert-Throw.ps1 @@ -75,7 +75,7 @@ function Assert-Throw { throw [Assertions.AssertionException]$Message } - $ScriptBlock + $err.ErrorRecord } function Get-Error ($ErrorRecord) { diff --git a/src/Exception/Get-ChildException.ps1 b/src/Exception/Get-ChildException.ps1 new file mode 100644 index 0000000..094700d --- /dev/null +++ b/src/Exception/Get-ChildException.ps1 @@ -0,0 +1,43 @@ +function Get-ChildException +{ + param + ( + [switch] + $Recurse, + + [Parameter(Mandatory, + ValueFromPipeline)] + [System.Management.Automation.ErrorRecord] + $ErrorRecord + ) + process + { + $ErrorRecord.Exception | Get-ChildExceptionImpl -Recurse:$Recurse + } +} + +function Get-ChildExceptionImpl +{ + param + ( + [switch] + $Recurse, + + [Parameter(Mandatory, + ValueFromPipeline)] + [System.Exception] + $Exception + ) + process + { + if ($null -eq $Exception.InnerException) + { + return + } + $Exception.InnerException + if ( $Recurse ) + { + $Exception.InnerException | Get-ChildExceptionImpl -Recurse:$Recurse + } + } +} \ No newline at end of file diff --git a/tst/Exception/Assert-Throw.Tests.ps1 b/tst/Exception/Assert-Throw.Tests.ps1 index cc37615..0a8169e 100644 --- a/tst/Exception/Assert-Throw.Tests.ps1 +++ b/tst/Exception/Assert-Throw.Tests.ps1 @@ -137,6 +137,13 @@ Describe "Assert-Throw" { { Get-Item "non-existing" } | Assert-Throw } } + + Context 'output' { + It 'outputs ErrorRecord' { + $r = {throw} | Assert-Throw + $r | Should -BeOfType ([System.Management.Automation.ErrorRecord]) + } + } } Describe "General try catch behavior" { diff --git a/tst/Exception/Get-ChildException.Tests.ps1 b/tst/Exception/Get-ChildException.Tests.ps1 new file mode 100644 index 0000000..f3631d8 --- /dev/null +++ b/tst/Exception/Get-ChildException.Tests.ps1 @@ -0,0 +1,69 @@ +InModuleScope Assert { +Describe Get-ChildException { + Mock Get-ChildExceptionImpl -Verifiable {'return value'} + try + { + throw 'message' + } + catch + { + $r = $_ | Get-ChildException -Recurse + } + It 'invokes Get-ChildExceptionImpl' { + Assert-MockCalled Get-ChildExceptionImpl -Times 1 -Exactly { + ($Exception.Message -eq 'message') -and + $Recurse + } + } + It 'returns value Get-ChildExceptionImpl' { + $r | Verify-Equal 'return value' + } +} +Describe Get-ChildExceptionImpl { + Context 'no InnerException' { + $r = [System.Exception]::new('message') | + Get-ChildExceptionImpl + It 'returns null' { + $r | Verify-Null + } + } + Context 'has InnerException' { + $r = [System.Exception]::new( + 'outer', + [System.Exception]::new('inner') + ) | + Get-ChildExceptionImpl + It 'returns InnerException' { + $r.Message | Verify-Equal 'inner' + } + } + Context 'nested InnerException' { + $e = [System.Exception]::new( + 'outermost', + [System.Exception]::new( + 'middle-outer', + [System.Exception]::new( + 'middle-inner', + [System.Exception]::new('innermost') + ) + ) + ) + Context 'don''t -Recurse' { + $r = $e | Get-ChildExceptionImpl + It 'returns only first descendant' { + $r.Count | Verify-Equal 1 + $r.Message | Verify-Equal 'middle-outer' + } + } + Context '-Recurse' { + $r = $e | Get-ChildExceptionImpl -Recurse + It 'returns all descendents, outermost-first' { + $r.Count | Verify-Equal 3 + $r[0].Message | Verify-Equal 'middle-outer' + $r[1].Message | Verify-Equal 'middle-inner' + $r[2].Message | Verify-Equal 'innermost' + } + } + } +} +} \ No newline at end of file