在Azure cmdlet调用上出现Pester模拟错误PSInvalidCastException

时间:2016-03-16 16:06:24

标签: unit-testing powershell azure mocking pester

我需要" 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
    }
  }

1 个答案:

答案 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验证。)