我需要" Pester-test"来自模块内部的PowerShell函数的2个Azure cmdlet, Get-AzureNetworkSecurityGroup 和 Set-AzureNetworkSecurityRule ,如下所示:
$nsg = Get-AzureNetworkSecurityGroup -Name $NsgName
Set-AzureNetworkSecurityRule -Name $NsgRule.name `
-Type Outbound `
# ... other properties here ...
-NetworkSecurityGroup $nsg |
Format-List -Property Name,Location,Label
参数$ NsgName,$ NsgRule不是那么重要,问题是我在模拟Set-AzureNetworkSecurityRule时遇到错误,如:
Mock Get-AzureNetworkSecurityGroup { return [PSCustomObject] @{ Name='Any' } }
Mock Set-AzureNetworkSecurityRule
Mock Format-List
错误说:
[-] Error occurred in Describe block 100ms
PSInvalidCastException: Cannot convert the "@{Name=Any}" value of type "System.Management.Automation.PSCustomObject" to type "Microsoft.WindowsAzure.Commands.ServiceManagement.Network.NetworkSecurityGroup.Model.INetworkSecurityGroup".
ArgumentTransformationMetadataException: Cannot convert the "@{Name=Any}" value of type "System.Management.Automation.PSCustomObject" to type "Microsoft.WindowsAzure.Commands.ServiceManagement.Network.NetworkSecurityGroup.Model.INetworkSecurityGroup".
ParameterBindingArgumentTransformationException: Cannot process argument transformation on parameter 'NetworkSecurityGroup'. Cannot convert the "@{Name=Any}" value of type "System.Management.Automation.PSCustomObject" to type "Microsoft.WindowsAzure.Commands.ServiceManagement.Network.NetworkSecurityGroup.Model.INetworkSecurityGroup".
很明显发生了什么,问题是我不知道如何模拟 INetworkSecurityGroup 类型的对象。如果模拟两个Azure cmdlet,我的期望最初是没问题的。
我还尝试使用 -MockWith 模拟 Set-AzureNetworkSecurityRule :
Mock Set-AzureNetworkSecurityRule -MockWith {@{NetworkSecurityGroup='test-stuff'}}
没有运气。
有人能指出我正确的方向吗? 提前致谢
完整描述声明更新
首先尝试
$environmentConfig = (Get-AzureEnvironmentConfig "Staging")
Describe 'Set-NetworkSecurityRuleFromObject' {
$role = ($environmentConfig.roles | Where { $_.role_name -eq 'Web'})
$nsgName = Get-NetworkSecurityGroupName -EnvironmentConfig $environmentConfig -Role $role
$rule = $role.nsg_rules.outbound[0]
Mock Get-AzureNetworkSecurityGroup
Mock Set-AzureNetworkSecurityRule
Set-NetworkSecurityRuleFromObject -NsgName -$nsgName -NsgRule $rule -NsgRuleType "Outbound"
It 'Should call mocked functions at least once' {
Assert-MockCalled Get-AzureNetworkSecurityGroup -Times 1 -Scope Describe
Assert-MockCalled Set-AzureNetworkSecurityRule -Times 1 -Scope Describe
}
}
关联的PS模块函数调用:
Get-AzureNetworkSecurityGroup -Name $NsgName |
Set-AzureNetworkSecurityRule -Name $NsgRule.name `
-Type $NsgRuleType `
# More parameter initialization here ...
-Protocol $NsgRule.protocol |
Format-List -Property Name,Location,Label
第二次尝试,另一种不起作用的PS功能:
$nsg = Get-AzureNetworkSecurityGroup -Name $NsgName
$nsg |
Set-AzureNetworkSecurityRule -Name $NsgRule.name `
-Type $NsgRuleType `
# More parameter initialization here ...
-Protocol $NsgRule.protocol |
Format-List -Property Name,Location,Label
第三次尝试
Describe 'Set-NetworkSecurityRuleFromObject' {
[ ... ]
Mock Get-AzureNetworkSecurityGroup { return [PSCustomObject] @{ Name='Any' } }
Mock Set-AzureNetworkSecurityRule
Set-NetworkSecurityRuleFromObject -NsgName -$nsgName -NsgRule $rule -NsgRuleType "Outbound"
It 'Should call mocked functions at least once' {
Assert-MockCalled Get-AzureNetworkSecurityGroup -Times 1 -Scope Describe
Assert-MockCalled Set-AzureNetworkSecurityRule -Times 1 -Scope Describe
}
}
答案 0 :(得分:2)
这仍然是Pester最具挑战性的事情之一。你需要以这样的方式模拟Get-AzureNetworkSecurityGroup
,以便它返回一个有效的对象以便稍后传递给Set-AzureNetworkSecurityGroup
,并且弄清楚如何做到这一点有时候会很棘手。在这种特殊情况下,它并不太糟糕:
Mock Get-AzureNetworkSecurityGroup {
return New-Object Microsoft.WindowsAzure.Commands.ServiceManagement.Network.NetworkSecurityGroup.Model.SimpleNetworkSecurityGroup('Any', 'someLocation', 'someLabel')
}
由于此函数参数是接口类型,您还可以在C#(或PowerShell v5)中编写一个实现该接口的快速类;有时这可能是更理想的,如果实际的班级开始做"东西"只要您创建一个实例。但是,这个SimpleNetworkSecurityGroup
类除了保存数据之外并没有真正做任何其他事情,并且按原样使用是安全的。 (已通过ILSpy验证。)