簡體   English   中英

如何使用 Pester 模擬對 exe 文件的調用?

[英]How to mock a call to an exe file with Pester?

在 PowerShell 中開發腳本,我需要調用外部可執行文件 (.exe)。 目前我正在使用 TDD 方法開發此腳本,因此我需要模擬對此 .exe 文件的調用。

我試試這個:

Describe "Create-NewObject" {
    Context "Create-Object" {
        It "Runs" {
            Mock '& "c:\temp\my.exe"' {return {$true}}
            Create-Object| Should Be  $true
        }
    }
}

我得到了這樣的回應:

Describing Create-NewObject
   Context Create-Object
    [-] Runs 574ms
      CommandNotFoundException: Could not find Command & "C:\temp\my.exe"
      at Validate-Command, C:\Program Files\WindowsPowerShell\Modules\Pester\Functions\Mock.ps1: line 801
      at Mock, C:\Program Files\WindowsPowerShell\Modules\Pester\Functions\Mock.ps1: line 168
      at <ScriptBlock>, C:\T\Create-NewObject.tests.ps1: line 13
Tests completed in 574ms
Passed: 0 Failed: 1 Skipped: 0 Pending: 0 Inconclusive: 0

有沒有辦法模擬這種調用而不將它們封裝在函數中?

我找到了一種方法來模擬對這個可執行文件的調用:

function Create-Object
{
   $exp = '& "C:\temp\my.exe"'
   Invoke-Expression -Command $exp
}

使用模擬的測試應該如下所示:

Describe "Create-NewObject" {
    Context "Create-Object" {
        It "Runs" {
            Mock Invoke-Expression {return {$true}} -ParameterFilter {($Command -eq '& "C:\temp\my.exe"')
            Create-Object| Should Be  $true
        }
    }
}

是的,不幸的是,從 Pester 4.8.1 開始:

  • 不能通過完整路徑模擬外部可執行文件(例如, C:\\Windows\\System32\\cmd.exe
  • 可以通過文件名(例如cmd )模擬它們,但請注意,在較舊的 Pester 版本中,僅針對顯式使用.exe擴展名(例如cmd.exe )的調用調用模擬 - 請參閱此(過時的)GitHub 問題

您自己的解決方法是有效的,但它涉及Invoke-Expression ,這很尷尬; 通常應避免使用Invoke-Expression

這是一個使用輔助函數Invoke-External的解決方法,它包裝外部程序的調用,並且作為一個函數,它本身可以被-ParameterFilter ,使用-ParameterFilter按可執行路徑過濾:

在您的代碼中,定義Invoke-External函數,然后使用它來調用c:\\temp\\my.exe

# Helper function for invoking an external utility (executable).
# The raison d'être for this function is to allow 
# calls to external executables via their *full paths* to be mocked in Pester.
function Invoke-External {
  param(
    [Parameter(Mandatory=$true)]
    [string] $LiteralPath,
    [Parameter(ValueFromRemainingArguments=$true)]
    $PassThruArgs
  )
  & $LiteralPath $PassThruArgs
}

# Call c:\temp\my.exe via invoke-External
# Note that you may pass arguments to pass the executable as usual (none here):
Invoke-External c:\temp\my.exe

然后,在 Pester 測試中模擬對c:\\temp\\my.exe的調用:

Mock Invoke-External -ParameterFilter { $LiteralPath -eq 'c:\temp\my.exe' } `
  -MockWith { $true }

注意:如果您的代碼中只有一個對外部可執行文件的調用,則可以省略
-ParameterFilter參數。

我試過這樣的東西,似乎工作。

$PathToExe = 'C:\Windows\System32\wevtutil.exe'
New-Item -Path function: -Name $PathToExe -Value { ... }
Mock $PathToExe { ... }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM