简体   繁体   中英

How to mock Azure PowerShell Cmdlets in Pester?

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.

I had to add the calling module name using the -ModuleName param for Mock:

Mock New-AzADApplication {
  @{
    ObjectID      = New-Guid
    ApplicationID = New-Guid
  }
} -ModuleName MyModule

Mock New-AzADAppCredential {$true} -ModuleName MyModule

Mock New-AzADServicePrincipal {$true} -ModuleName MyModule

Mock Read-Host {ConvertTo-SecureString -String 'Password' -AsPlainText -Force} -ModuleName MyModule

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM