So I've been trying to unit test my Azure deployment script and not been able to mock the Azure cmdlets. Even with the mocks in place they are executed during the tests.
This is my PowerShell Version.
Name Value
---- -----
PSVersion 5.1.16299.1146
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.16299.1146
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
And im on Version 4.8.1 of Pester.
So this is what my actual code looks like, that i was trying to get to work. First the function:
function CleanUp-Resources {
Set-AzContext $DeploymentSubscriptionName | Out-Null
$resGroup = Get-AzResourceGroup -Name $script:devtestlabRGName -ErrorAction SilentlyContinue
if (!$resGroup) {
$Global:Error.RemoveAt(0)
}
else {
Write-SitAzLog "Removing resource group and all generated resources"
Remove-SitAzRGWithLocks $resGroup.ResourceGroupName
}
}
As you can see it's just a simple function to remove a resourceGroup if it exists.
Now the test code:
Describe "CleanUp-Resources" -Tags "Disabled", "Unit"{
Mock Write-SitAzLog {}
Mock Set-AzContext {}
Context "res group not found" {
$cnt = $Error.Count
Mock Get-AzResourceGroup {
throw "Not found"
}
It "deletes the error message from count" {
CleanUp-Resources
Assert-MockCalled Get-AzResourceGroup
$Error.Count | Should Be $cnt
}
}
}
So my understanding of mocking is that this should stop the actual Set-AzContext function from being run as it is mocked with an empty script block. But unfortunately the Set-AzContext throws an error that the value for parameter context is null, which shows that it's trying to execute the normal cmdlet. Mocking cmdlets from other modules worked just fine so I'm guessing it has somethoing to do with the Azure module in particular.
Ty for any feedback.
The working solution for me is to provide some (mocked) input to the mocked command - without it, mock is not hit.
Code:
$subscription = Get-AzSubscription -SubscriptionId 'xyz'
if ($null -ne $subscription) {
Set-AzContext -SubscriptionObject $subscription | Out-Null
}
Mock:
Mock Get-AzSubscription -ParameterFilter {$SubscriptionId -eq 'xyz'}{
return New-Object Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription
}
Mock Set-AzContext
and in this case both mocks are hit. Without an object returned from Get-AzSubscription, Set-AzContext mock is not hit and pester returns error.