如何在 Pester 中模拟 Azure PowerShell Cmdlet?
How to mock Azure PowerShell Cmdlets in Pester?
所以我一直在尝试对我的 Azure 部署脚本进行单元测试,但无法模拟 Azure cmdlet。即使有了模拟,它们也会在测试期间执行。
这是我的 PowerShell 版本。
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
我正在使用 Pester 的 4.8.1 版。
这就是我尝试开始工作的实际代码的样子。
首先是函数:
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
}
}
如您所见,这只是一个删除资源组(如果存在)的简单函数。
现在测试代码:
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
}
}
}
所以我对模拟的理解是,这应该阻止实际的 Set-AzContext 函数成为 运行,因为它是用空脚本块模拟的。
但不幸的是,Set-AzContext 抛出参数上下文的值为 null 的错误,这表明它正在尝试执行正常的 cmdlet。
来自其他模块的模拟 cmdlet 工作得很好,所以我猜它与 Azure 模块特别有关。
感谢任何反馈。
我的工作解决方案是为模拟命令提供一些(模拟的)输入——没有它,模拟不会被命中。
代码:
$subscription = Get-AzSubscription -SubscriptionId 'xyz'
if ($null -ne $subscription) {
Set-AzContext -SubscriptionObject $subscription | Out-Null
}
模拟:
Mock Get-AzSubscription -ParameterFilter {$SubscriptionId -eq 'xyz'}{
return New-Object Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription
}
Mock Set-AzContext
在这种情况下,两个模拟都被命中。如果没有从 Get-AzSubscription 返回的对象,则不会命中 Set-AzContext 模拟并引发 returns 错误。
我必须使用 Mock 的 -ModuleName 参数添加调用模块名称:
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
所以我一直在尝试对我的 Azure 部署脚本进行单元测试,但无法模拟 Azure cmdlet。即使有了模拟,它们也会在测试期间执行。
这是我的 PowerShell 版本。
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
我正在使用 Pester 的 4.8.1 版。
这就是我尝试开始工作的实际代码的样子。 首先是函数:
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
}
}
如您所见,这只是一个删除资源组(如果存在)的简单函数。
现在测试代码:
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
}
}
}
所以我对模拟的理解是,这应该阻止实际的 Set-AzContext 函数成为 运行,因为它是用空脚本块模拟的。 但不幸的是,Set-AzContext 抛出参数上下文的值为 null 的错误,这表明它正在尝试执行正常的 cmdlet。 来自其他模块的模拟 cmdlet 工作得很好,所以我猜它与 Azure 模块特别有关。
感谢任何反馈。
我的工作解决方案是为模拟命令提供一些(模拟的)输入——没有它,模拟不会被命中。
代码:
$subscription = Get-AzSubscription -SubscriptionId 'xyz'
if ($null -ne $subscription) {
Set-AzContext -SubscriptionObject $subscription | Out-Null
}
模拟:
Mock Get-AzSubscription -ParameterFilter {$SubscriptionId -eq 'xyz'}{
return New-Object Microsoft.Azure.Commands.Profile.Models.PSAzureSubscription
}
Mock Set-AzContext
在这种情况下,两个模拟都被命中。如果没有从 Get-AzSubscription 返回的对象,则不会命中 Set-AzContext 模拟并引发 returns 错误。
我必须使用 Mock 的 -ModuleName 参数添加调用模块名称:
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