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!