Powershell 如何正确地模拟函数以使用Pester返回自定义属性?

Powershell 如何正确地模拟函数以使用Pester返回自定义属性?,powershell,pester,Powershell,Pester,我对PowerShell有点陌生,尤其是纠缠测试。我似乎无法为正在进行Pester测试的函数重新创建场景 代码如下: $State = Get-Status if(State) { switch ($State.Progress) { 0 { Write-Host "Session for $Name not initiated. Retrying." } 100{ Write-Host "Session for $

我对PowerShell有点陌生,尤其是纠缠测试。我似乎无法为正在进行Pester测试的函数重新创建场景

代码如下:

    $State = Get-Status

    if(State) {
    switch ($State.Progress) {
    0 {
       Write-Host "Session for $Name not initiated. Retrying."
      }

    100{
     Write-Host "Session for $Name at $($State.Progress) percent"
      }

    default {
     Write-Host "Session for $Name in progress (at $($State.Progress) 
    percent)."
       }
    }
    Context 'State Progress returns 0' {
    mock Get-Status {return $true} -Verifiable
    $State = [PSCustomObject]@{Progress = 0}
    $result =  Confirm-Session 
       it 'should be' {
           $result | should be "Session for $Name not initiated. Retrying."
        }
    }
$Name = 'SomeName'

#Had to define an empty function in order to be able to Mock it. You don't need to do this in your code as you have the real function.
Function Get-Status { }

#I assumed based on your code all of this code was wrapped as a Function called Confirm-Session
Function Confirm-Session  {
    $State = Get-Status

    if ($State) {
        switch ($State.Progress) {
        0 {
            "Session for $Name not initiated. Retrying."
          }

        100{
            "Session for $Name at $($State.Progress) percent"
          }

        default {
            "Session for $Name in progress (at $($State.Progress) percent)."
           }
        }
    }
}

#Pester tests for the above code:
Describe 'State Progress returns 0' {
    mock Get-Status {
        [PSCustomObject]@{Progress = 0}
    } -Verifiable

    #$State = [PSCustomObject]@{Progress = 0}

    $result = Confirm-Session

    it 'should be' {
        $result | should be "Session for $Name not initiated. Retrying."
    }

    it 'should call the verifiable mocks' {
        Assert-VerifiableMocks
    }
 }
我模拟了
Get Status
以返回true,这样代码路径将进入
if
块中,但是结果没有
$State.Progress的任何值

就代码路径而言,我的测试总是进入默认块。我试过了 创建自定义对象
$State=[PSCustomObject]@{Progress=0}
无效

这是我的纠缠测试的一部分:

    $State = Get-Status

    if(State) {
    switch ($State.Progress) {
    0 {
       Write-Host "Session for $Name not initiated. Retrying."
      }

    100{
     Write-Host "Session for $Name at $($State.Progress) percent"
      }

    default {
     Write-Host "Session for $Name in progress (at $($State.Progress) 
    percent)."
       }
    }
    Context 'State Progress returns 0' {
    mock Get-Status {return $true} -Verifiable
    $State = [PSCustomObject]@{Progress = 0}
    $result =  Confirm-Session 
       it 'should be' {
           $result | should be "Session for $Name not initiated. Retrying."
        }
    }
$Name = 'SomeName'

#Had to define an empty function in order to be able to Mock it. You don't need to do this in your code as you have the real function.
Function Get-Status { }

#I assumed based on your code all of this code was wrapped as a Function called Confirm-Session
Function Confirm-Session  {
    $State = Get-Status

    if ($State) {
        switch ($State.Progress) {
        0 {
            "Session for $Name not initiated. Retrying."
          }

        100{
            "Session for $Name at $($State.Progress) percent"
          }

        default {
            "Session for $Name in progress (at $($State.Progress) percent)."
           }
        }
    }
}

#Pester tests for the above code:
Describe 'State Progress returns 0' {
    mock Get-Status {
        [PSCustomObject]@{Progress = 0}
    } -Verifiable

    #$State = [PSCustomObject]@{Progress = 0}

    $result = Confirm-Session

    it 'should be' {
        $result | should be "Session for $Name not initiated. Retrying."
    }

    it 'should call the verifiable mocks' {
        Assert-VerifiableMocks
    }
 }

有几个问题:

  • 根据4c的评论,您的Mock可能因为作用域而没有被调用(除非您的上下文周围没有显示descripe块)。如果您将
    上下文
    更改为
    描述
    ,然后使用
    断言可验证的Mock
    ,您可以看到Mock确实会被调用
  • 无法验证使用
    Write Host
    的代码的输出,因为此命令不会写入正常的输出流(它会写入主机控制台)。如果删除
    Write Host
    ,以便将字符串返回到标准输出流,则代码可以工作
  • 您可以按照建议使用
    [PSCustomObject]@{Progress=0}
    模拟
    .Progress
    属性的输出,但我认为这应该在
    Get Status
    的模拟中
这里有一个最小的/可验证的示例:

    $State = Get-Status

    if(State) {
    switch ($State.Progress) {
    0 {
       Write-Host "Session for $Name not initiated. Retrying."
      }

    100{
     Write-Host "Session for $Name at $($State.Progress) percent"
      }

    default {
     Write-Host "Session for $Name in progress (at $($State.Progress) 
    percent)."
       }
    }
    Context 'State Progress returns 0' {
    mock Get-Status {return $true} -Verifiable
    $State = [PSCustomObject]@{Progress = 0}
    $result =  Confirm-Session 
       it 'should be' {
           $result | should be "Session for $Name not initiated. Retrying."
        }
    }
$Name = 'SomeName'

#Had to define an empty function in order to be able to Mock it. You don't need to do this in your code as you have the real function.
Function Get-Status { }

#I assumed based on your code all of this code was wrapped as a Function called Confirm-Session
Function Confirm-Session  {
    $State = Get-Status

    if ($State) {
        switch ($State.Progress) {
        0 {
            "Session for $Name not initiated. Retrying."
          }

        100{
            "Session for $Name at $($State.Progress) percent"
          }

        default {
            "Session for $Name in progress (at $($State.Progress) percent)."
           }
        }
    }
}

#Pester tests for the above code:
Describe 'State Progress returns 0' {
    mock Get-Status {
        [PSCustomObject]@{Progress = 0}
    } -Verifiable

    #$State = [PSCustomObject]@{Progress = 0}

    $result = Confirm-Session

    it 'should be' {
        $result | should be "Session for $Name not initiated. Retrying."
    }

    it 'should call the verifiable mocks' {
        Assert-VerifiableMocks
    }
 }
返回:

Describing State Progress returns 0
  [+] should be 77ms
  [+] should call the verifiable mocks 7ms

我会想象你在一个错误的范围内模拟它\level应该
if(state)
be
if($state)
?另外,
确认会话
功能出现在哪里?你能把你的代码变成MCVE吗!我不相信我错过了。你说得对,state确实是$state。顺便说一句,Confirm-Session是我正在测试的函数。哇!非常感谢马克·拉格。还有很长的路要走。