I have the following declarations:
function Get-Datastore { [CmdletBinding()] param ($Name, $Id, $Server, [Parameter(ValueFromPipeline = $true)]$Location) }
function Get-ScsiLun { [CmdletBinding()] param ($Server, [Parameter(ValueFromPipeline = $true)]$Datastore) }
With these simple Mocks:
Mock Get-Datastore {
return $mockDatastores
}
Mock Get-ScsiLun {
return $mockLuns
}
The partial code (from Get-XxxScsiLun
function):
$datastores = $VMHost |
Get-Datastore -Server $Server -PipelineVariable "datastore" |
Where-Object { $datastore.Type -eq "VMFS" } |
Get-ScsiLun -Server $Server |
Select-Object -Property "CanonicalName", @{ "Name" = "Datastore"; "Expression" = { $datastore.Name } }
The Pester test (simplified):
It "Should return the luns" {
$result = Get-XxxScsiLun -VMHost $mockVmHost
$result | Should -HaveCount 2
}
The Pester test fails with:
[-] Should return the luns 21ms
RuntimeException: The variable '$datastore' cannot be retrieved because it has not been set.
So my question is: How can I support -PipelineVariabele
from Pester?
Note1: I don't want to change the original code, so using $_
instead of the pipeline variable is not desired
Note2: Adding Set-Variable -Name "datastore" -Scope 3 -Value $mockDatastores
to the Get-Datastore
mock defines the $datastore
in the correct scope, but containing all datastores instead of 1 (per pipeline call)
Update: Working example to show the error:
$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
function Get-XxxScsiLun
{
$datastores = Get-Datastore -PipelineVariable "datastore" |
Where-Object { $datastore.Type -eq "VMFS" }
return $datastores
}
Describe "Happy flow" {
BeforeAll {
function Get-Datastore { [CmdletBinding()] param () }
$mockDatastores = @(
[PSCustomObject]@{ "Name" = "ds1"; "Type" = "VMFS" },
[PSCustomObject]@{ "Name" = "ds2"; "Type" = "NFS" }
)
Mock Get-Datastore {
return $mockDatastores
}
}
It "Should return the luns" {
$result = Get-XxxScsiLun
$result | Should -HaveCount 1
}
}