Following on from the previous Mocking Missing Cmdlets with Pester post, I also encountered another interesting problem when attempting to mock cmdlets that were not present on the test system. This one is more of an edge-case, hence its own post. Just like last time, the tests worked when I had the Hyper-V cmdlets installed, but failed when running within an Appveyor VM.
It’s probably not uncommon that you will need to ensure that the code under test should throw an error here-and-there. Here is a pseudo-example that tests that Get-VM writes an error when passed with a non-existent VM name:
Describe 'Mocking ErrorAction Example' { Function Get-VM { param ($Name) } InModuleScope 'xVMHyper-V' { It 'Get-VM Throws' { Mock Get-VM -ParameterFilter { $Name -eq 'TestVM' } -MockWith { Write-Error 'Oops' } { Get-VM -Name 'TestVM' -ErrorAction Stop } | Should Throw; } } }
When this test is run it fails:
Describing Mocking ErrorAction Example Write-Error 'Oops' : Oops At C:\Program Files\WindowsPowerShell\Modules\Pester\Functions\Mock.ps1:709 char:21 + & $___ScriptBlock___ @___BoundParameters___ @___ArgumentList ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException [-] Get-VM Throws 176ms Expected: the expression to throw an exception at line: 6 in D:\Users\Iain\Desktop\PesterDemo.Tests.ps1 Tests completed in 176ms Passed: 0 Failed: 1 Skipped: 0 Pending: 0
The problem here is that the stub function is not an advanced function and the –ErrorAction preference switch is ignored! This is easily resolved by adding the [CmdletBinding()] attribute to the stub function definition:
Describe 'Mocking ErrorAction Example' { Function Get-VM { [CmdletBinding()] param ($Name) } InModuleScope 'xVMHyper-V' { It 'Get-VM Throws' { Mock Get-VM -ParameterFilter { $Name -eq 'TestVM' } -MockWith { Write-Error 'Oops' } { Get-VM -Name 'TestVM' -ErrorAction Stop } | Should Throw; } } }
Running the test now results in the expected output:
Describing Mocking ErrorAction Example [+] Get-VM Throws 177ms Tests completed in 177ms Passed: 1 Failed: 0 Skipped: 0 Pending: 0
This is not a Pester issue and it’s not a Powershell issue either. It’s just the way the normal Powershell functions work. But, just in case someone else runs into it I thought it would be worth quickly documenting!