0

我需要从模块内的 PowerShell 函数中“纠缠测试”2 个 Azure cmdlet、Get-AzureNetworkSecurityGroupSet-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
    }
  }
4

1 回答 1

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

于 2016-03-17T12:55:26.933 回答