[英]How should a Mock function accept pipeline input in Pester?
我對 Pester 很陌生,我正在嘗試在 PowerShell 中為一個非常小而簡單的函數構建測試:
function Toggle-Notepad {
if (-not ( Get-Process notepad -ErrorAction SilentlyContinue ) )
{
Start-Process -FilePath Notepad
}
else
{
get-process notepad | stop-process
}
}
如果記事本未運行,則此功能僅啟動記事本,否則,如果它正在運行,則將其停止。
我設計的測試是這樣的:
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"
Describe "Toggle-Notepad" {
Mock Stop-Process { "Process object passed! Stopping notepad!" }
Mock Start-Process { "Notepad is not running,starting it!" } -ParameterFilter { $Filepath -eq "Notepad" }
It "Starts notepad if it is not running" {
Toggle-Notepad | Should be "Notepad is not running,starting it!"
}
It "Stops notepad if it is running" {
Toggle-Notepad | Should be "Process object passed ! Stopping notepad!"
}
}
上述測試按預期運行。
如何重寫Stop-Process
函數,以便可以指定此版本用於接受管道輸入?
我試過這個,但它不起作用:
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"
Describe "Toggle-Notepad" {
Mock stop-process { "Process object passed ! Stopping notepad" } -ParameterFilter { $InputObject -is "System.Diagnostics.Process" }
Mock Start-Process {"Notepad is not running,starting it!"} -ParameterFilter { $Filepath -eq "Notepad" }
It "Starts notepad if it is not running" {
Toggle-Notepad | Should be "Notepad is not running,starting it!"
}
It "Stops notepad if it is running" {
Toggle-Notepad | Should be "Process object passed ! Stopping notepad!"
}
}
由於Stop-Process
函數正在接受管道輸入,我的目標是模擬類似的函數,而不是創建一個不接受任何參數的通用Stop-Process
函數。
有沒有 Pester 專家可以提供幫助?
您通常不需要在Mock
手動定義參數,因為被Mock
的函數的參數是在 Mock 中自動創建的。
您的Stop-Process
Mock 不工作的原因是因為您已經使用-ParameterFilter
屬性定義了它,這導致它僅在定義的 Parameter 為真時才被調用。 您的過濾器不起作用,因為您將對象類型引用為字符串( "System.Diagnostics.Process"
)而不是類型(用方括號聲明)。
Mock 的正確代碼是:
Mock stop-process { "Process object passed ! Stopping notepad!" } -ParameterFilter { $InputObject -is [System.Diagnostics.Process[]] }
我直接向 Pester 開發團隊詢問了這個問題,他們提出了一個更簡單的解決方案,即-ParameterFilter { $InputObject }
因為如果它沒有填充該類型的有效對象,它將為 null。
這是一個完整的例子:
Describe 'Mocking stop-process' {
Mock Stop-Process {
Write-Host "Mock stopping: $InputObject"
} -ParameterFilter { $InputObject }
It 'Should mock stopping the notepad process' {
Get-Process notepad | Stop-Process | Should Be $null
}
}
另外僅供參考,從 Pester 3.4.4 開始,現在有一個New-MockObject命令,允許您創建任何類型的假對象:
New-MockObject 是一個 Pester 函數(在 Pester 3.4.4 中引入),它允許您創建幾乎任何類型的“假”對象以在 Pester 模擬中運行。 這些“假對象”允許您的模擬返回與其模擬的函數相同的類型,以將結果傳遞給強類型的實體。
在您的場景中沒有必要,但我認為您可能會發現它相關/有趣。
您可以像任何其他函數一樣模擬接受管道值的函數:
Describe "Toggle-Notepad" {
Mock Stop-Process {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true)]
$InputObject
)
return "Process object passed! Stopping notepad"
} -ParameterFilter { $InputObject -is "System.Diagnostics.Process" }
Mock Start-Process {
return "Notepad is not running, starting it!"
} -ParameterFilter { $Filepath -eq "Notepad" }
It "Starts notepad if it is not running" {
Toggle-Notepad | Should be "Notepad is not running, starting it!"
}
It "Stops notepad if it is running" {
Toggle-Notepad | Should be "Process object passed! Stopping notepad!"
}
}
另請注意,您Stop-Process
存在拼寫錯誤,因此無法正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.