powershell - 如何使用 Pester 模拟 $host.ui.PromptForChoice

标签 powershell pester

考虑下面的 Powershell 代码,有没有办法在没有 internalMenuWrapper 函数的情况下模拟 $host.ui.PromptForChoice

<#
    .Synopsis
        wrap the menu so we can mock calls to it
#>
function internalMenuWrapper {
    param (
        [Parameter(Mandatory=$true)]
        $prompt,
        [Parameter(Mandatory=$true)]
        $options
    )
    return = $host.ui.PromptForChoice("Waiting for user input", $prompt, [System.Management.Automation.Host.ChoiceDescription[]]$options, 0)
}

<#
    .Synopsis
        Create a menu with an array of choices and return the result
#>
function Invoke-Menu($prompt, $opts) {
        $options = @()
        foreach ($opt in $opts) {
                $options += $(new-object System.Management.Automation.Host.ChoiceDescription $opt)
        }
        $index = internalMenuWrapper $prompt $options
        $opts[$index]
}

Describe 'Invoke-Menu' {
    Context "when called" {
        It "returns the object that was selected" {
            #mock fails
            Mock internalMenuWrapper { return 0 }
            $result = Invoke-Menu "test menu" @("pass", "fail")
            $result | Should -Be "pass"
        }
    }
}

最佳答案

Mike Shepard在评论中指出,Pester 不支持模拟方法,只能模拟命令(cmdlet、函数、别名、外部程序).

您可以使用 Get-Host cmdlet(而不是 $host)解决该问题并模拟that:

function Invoke-Menu($prompt, $choices) {

  $choiceObjects = [System.Management.Automation.Host.ChoiceDescription[]] $choices

  # Use Get-Host instead of $host here; $host cannot be mocked, but Get-Host can.
  $index = (Get-Host).ui.PromptForChoice("Waiting for user input", $prompt, $choiceObjects, 0)

  $choices[$index]

}

Describe 'Invoke-Menu' {
  Context "when called" {
      It "returns the object that was selected" {
        # Mock Get-Host with a dummy .ui.PromptForChoice() method that instantly
        # returns 0 (the first choice).
        Mock Get-Host { 
          [pscustomobject] @{ 
            ui = Add-Member -PassThru -Name PromptForChoice -InputObject ([pscustomobject] @{}) -Type ScriptMethod -Value { return 0 }
          }          
        }
        Invoke-Menu 'test menu'  '&pass', '&fail' | Should -Be '&pass'
      }
  }
}

正如您指出的on GitHub ,如果建议的 Read-Choice cmdlet 曾经实现过(作为 $host.ui.PromptForChoice() 的 PS 友好包装器),则可以直接模拟它(并且没有要测试的自定义代码)。

关于powershell - 如何使用 Pester 模拟 $host.ui.PromptForChoice,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57698737/

相关文章:

powershell - 针对Azure中部署插槽的Web配置更改

powershell - 在Powershell中使用UFormat转换时为什么会出现语法错误

powershell - 有没有办法使用 PowerShell 从半结构化文本文件创建对象?

powershell - 起始位转移与paster兼容吗

node.js - 使用 Pester 覆盖 powershell 脚本

powershell - Pester 示例脚本在 Windows 10 上获取 "-Be is not a valid Should operator",在 Ubuntu 上运行良好

powershell - XDELETE 不删除 ElasticSearch 中的索引

.net - 在 64 位环境中使用 32 位 COM 对象

powershell - 模板验证错误 - 错误 : Code=InvalidTemplate; Message=Deployment template validation failed:

powershell - "Path cannot be found"Pester测试结果