Testing of ForEach-Object -Parallel
Checklist
- [X] Feature request has a meaningful title
- [X] I have searched the existing issues. See all issues
- [X] I have tested using the latest version of Pester. See Installation and update guide.
Summary of the feature request
$TimeToSleep = 5
1..10 | ForEach-Object -Parallel {
$TimeToSleep = $using:TimeToSleep
Start-Sleep $TimeToSleep
} -ThrottleLimit 5
I would like to be able to mock a function inside of a "ForEach-Object -Parallel". In the above rather contrieved example I would like to be able to mock the Start-Sleep function
Thx
How should it work?
No response
Unfortunately that's not possible.
Using -Parallel runs the scriptblock-code in new PowerShell runspaces (threads). The new runspaces doesn't share any state like imported modules, variables etc. with your normal session. So the Pester-module and any knowledge of existing mocks are invisble inside.
Sorry to hear that it's not possible. Any recommendation or best practises on how to implement multithreading in powershell in order to make it testable with Pester?
It's mostly mocking objects and commands that won't work.
You can test the results of any code using multithreading, so maybe focus on integration tests against test-data/environments?
Running into this same limitation of Pester. Some easy repro code:
Describe 'it should be' {
BeforeAll {
$realCmdLet = @{
InvokeCommand = Get-Command Invoke-Command
}
Mock Invoke-Command {
& $realCmdLet.InvokeCommand -Scriptblock {
1
} -ComputerName $env:COMPUTERNAME
}
$testData = @(
@{ComputerName = 'PC1' }
@{ComputerName = 'PC2' }
)
}
It 'green' {
$testData | ForEach-Object {
Invoke-Command -ComputerName $_.ComputerName -ScriptBlock { 1 }
}
Should -Invoke Invoke-Command -Times 1 -Exactly -ParameterFilter {
$ComputerName -eq 'PC1'
}
Should -Invoke Invoke-Command -Times 1 -Exactly -ParameterFilter {
$ComputerName -eq 'PC2'
}
}
It 'green' {
$testData | ForEach-Object -Parallel {
Invoke-Command -ComputerName $_.ComputerName -ScriptBlock { 1 }
}
Should -Invoke Invoke-Command -Times 1 -Exactly -ParameterFilter {
$ComputerName -eq 'PC1'
}
Should -Invoke Invoke-Command -Times 1 -Exactly -ParameterFilter {
$ComputerName -eq 'PC2'
}
}
}
The last test fails because of Foreach-Object -Parallel creating its own runspaces in which Pester can't utilise mocks.
@nohwnd @fflaten is there really no way around this?
It would maybe be an idea if Pester could remove the -Parallel switch and run it in the same thread just for debugging purposes. But that would also entail replacing variables that start with $using:xxx.
Related StackOverflow question.