Developing a script in PowerShell, I require to call an external executable file(.exe). currently I am developing this script with a TDD approach, therefore I require to mock the called to this .exe file.
I try this :
Describe "Create-NewObject" {
Context "Create-Object" {
It "Runs" {
Mock '& "c:\temp\my.exe"' {return {$true}}
Create-Object| Should Be $true
}
}
}
I got this response:
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
Is there a way to mock this kind of calls without encapsulate them inside a function?
I found a way to mock the call to this executable files:
function Create-Object
{
$exp = '& "C:\temp\my.exe"'
Invoke-Expression -Command $exp
}
And the test with the mock should looks like:
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
}
}
}
Yes, unfortunately, as of Pester 4.8.1:
C:\Windows\System32\cmd.exe
)cmd
), but beware that in older Pester versions the mock is only called for invocations that explicitly use the .exe
extension (e.g., cmd.exe
) - see this (obsolete) GitHub issue
Your own workaround is effective, but it involves Invoke-Expression
, which is awkward; Invoke-Expression
should generally be avoided
Here's a workaround that uses a helper function, Invoke-External
, which wraps the invocation of external programs and, as a function, can itself be mocked, using a -ParameterFilter
to filter by executable path:
In your code, define the Invoke-External
function and then use it to make your call to 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
Then, to mock the call to c:\temp\my.exe
in your Pester tests:
Mock Invoke-External -ParameterFilter { $LiteralPath -eq 'c:\temp\my.exe' } `
-MockWith { $true }
Note: If you only have one call to an external executable in your code, you can omit the -ParameterFilter
argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With