unit-testing - Azure cmdlet 调用上出现 Pester 模拟错误 PSInvalidCastException

标签 unit-testing powershell azure mocking pester

我需要从模块内的 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
    }
  }

最佳答案

这仍然是 Pester 面临的最具挑战性的事情之一。您需要以某种方式模拟 Get-AzureNetworkSecurityGroup,使其返回一个有效对象,以便稍后传递给 Set-AzureNetworkSecurityGroup,并且有时可以弄清楚如何做到这一点很棘手。在这个特定的例子中,情况还不错:

Mock Get-AzureNetworkSecurityGroup {
    return New-Object Microsoft.WindowsAzure.Commands.ServiceManagement.Network.NetworkSecurityGroup.Model.SimpleNetworkSecurityGroup('Any', 'someLocation', 'someLabel')
}

由于此函数参数是接口(interface)类型,因此您还可以用 C#(或 PowerShell v5)编写一个快速类来实现该接口(interface);有时,如果实际的类在您创建实例后立即开始执行“操作”,这可能会更理想。但是,这个 SimpleNetworkSecurityGroup 类除了保存数据之外并没有真正执行任何操作,并且按原样使用是安全的。 (使用 ILSpy 验证。)

关于unit-testing - Azure cmdlet 调用上出现 Pester 模拟错误 PSInvalidCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36041017/

相关文章:

unit-testing - 许多测试类还是一个测试类具有多种方法?

javascript - 如何模拟具有 require 字段的 Angular Directive(指令)

powershell - 在 Powershell 中使用 if 语句移动文件

Powershell从rabbitmqctl获取输出并解析异常

sql-server - SQL Server : group by date time and first_value

c# - System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath 对于单元测试为 null

c# - 集成测试数据库重建性能

powershell - 如何使用Powershell遍历CSV行和导出表

azure - 未使用适用于云服务的 2.0 Azure SDK 记录 RoleEntryPoint 跟踪调用

git - “找不到所选帐户的有效 Azure DevOps 团队项目”Azure Synapse GIT 配置