admin管理员组文章数量:1291077
I am receiving the following error when trying get this pester test to work for a function that receives a pipeline parameter.
"An error occured running Pester: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input."
Module: MyModule.psm1
function MyFunction {
"piping to Write-Output" | Write-Output
$dataTable = New-Object System.Data.DataTable
$dataTable | MyPipelineFunction
}
function MyPipelineFunction {
[CmdletBinding()]
param (
[Parameter(
Mandatory = $true,
ValueFromPipeline=$true)]
[System.Data.DataTable] $DataTable
)
Write-Host "hello world"
}
Pester Test
Import-Module "C:\temp\StackOverflow\PipelineMock\MyModule\MyModule.psm1" -Force
InModuleScope 'MyModule' {
Describe 'MyFunction' {
BeforeAll {
# Create a sample DataTable
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("Column1", [System.String])
$row = $dataTable.NewRow()
$row["Column1"] = "Sample Data"
$dataTable.Rows.Add($row)
# Mock the DataTable creation in MyInternalFunction
Mock -CommandName New-Object -ParameterFilter { $TypeName -eq 'System.Data.DataTable' } -MockWith { return $dataTable }
Mock MyPipelineFunction -MockWith {[CmdletBinding()] param (
[Parameter(
Mandatory = $true,
ValueFromPipeline=$true)]
[System.Data.DataTable] $DataTable
)
}
Mock Write-Output {}
}
It 'should call MyPipelineFunction' {
MyFunction
Assert-MockCalled -CommandName Write-Output -Exactly 1 -Scope It
Assert-MockCalled -CommandName New-Object -Exactly 1 -Scope It -ParameterFilter {$TypeName -eq 'System.Data.DataTable' }
Assert-MockCalled -CommandName MyPipelineFunction -Exactly 1 -Scope It -ParameterFilter {$DataTable -eq $dataTable}
}
}
}
I've several different Mock approaches and parameter filters given what I found out there. The Pester site doesn't seem to have any clear guidance on this. I was able to write a basic mock for Write-Output where I piped text to it and that works fine.
Can anyone see the problem?
I am receiving the following error when trying get this pester test to work for a function that receives a pipeline parameter.
"An error occured running Pester: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input."
Module: MyModule.psm1
function MyFunction {
"piping to Write-Output" | Write-Output
$dataTable = New-Object System.Data.DataTable
$dataTable | MyPipelineFunction
}
function MyPipelineFunction {
[CmdletBinding()]
param (
[Parameter(
Mandatory = $true,
ValueFromPipeline=$true)]
[System.Data.DataTable] $DataTable
)
Write-Host "hello world"
}
Pester Test
Import-Module "C:\temp\StackOverflow\PipelineMock\MyModule\MyModule.psm1" -Force
InModuleScope 'MyModule' {
Describe 'MyFunction' {
BeforeAll {
# Create a sample DataTable
$dataTable = New-Object System.Data.DataTable
$dataTable.Columns.Add("Column1", [System.String])
$row = $dataTable.NewRow()
$row["Column1"] = "Sample Data"
$dataTable.Rows.Add($row)
# Mock the DataTable creation in MyInternalFunction
Mock -CommandName New-Object -ParameterFilter { $TypeName -eq 'System.Data.DataTable' } -MockWith { return $dataTable }
Mock MyPipelineFunction -MockWith {[CmdletBinding()] param (
[Parameter(
Mandatory = $true,
ValueFromPipeline=$true)]
[System.Data.DataTable] $DataTable
)
}
Mock Write-Output {}
}
It 'should call MyPipelineFunction' {
MyFunction
Assert-MockCalled -CommandName Write-Output -Exactly 1 -Scope It
Assert-MockCalled -CommandName New-Object -Exactly 1 -Scope It -ParameterFilter {$TypeName -eq 'System.Data.DataTable' }
Assert-MockCalled -CommandName MyPipelineFunction -Exactly 1 -Scope It -ParameterFilter {$DataTable -eq $dataTable}
}
}
}
I've several different Mock approaches and parameter filters given what I found out there. The Pester site doesn't seem to have any clear guidance on this. I was able to write a basic mock for Write-Output where I piped text to it and that works fine.
Can anyone see the problem?
Share Improve this question asked Feb 13 at 19:21 KurtisKurtis 374 bronze badges 4 |1 Answer
Reset to default 1Note that Assert-MockCalled
is obsolete, the replacement would be Should -Invoke
. See the documentation for details.
There 3 things you must know before showing you how the Pester code should look:
What Mathias mentioned in his comment, even tho
DataTable
is not anIEnumerable
the pipeline will enumerate it, essentially by enumerating theDataRowCollection
, seeBinders.cs#L613-L638
. So, If you want to pipe it, and your function to receive it as-is, you have to either useWrite-Output -NoEnumerate
or the,
operator:function MyFunction { 'piping to Write-Output' | Write-Output $dataTable = New-Object System.Data.DataTable , $dataTable | MyPipelineFunction }
The same consideration will apply in your
Mock -CommandName New-Object
call, you will have to use-MockWith { , $dataTable }
there (notice the,
before the variable).This enumeration behavior mentioned for the pipeline also applies when Pester invokes the
-MockWith
scriptblock, making its output to be enumerated, to put it visually:$shouldBeDT = & { $dataTable = New-Object System.Data.DataTable $null = $dataTable.Columns.Add('Column1', [System.String]) $row = $dataTable.NewRow() $row['Column1'] = 'Sample Data' $dataTable.Rows.Add($row) $dataTable } $shouldBeDT.GetType() # But is a `DataRow`
You should not define a
param
block in your-MockWith
scriptblock, as suggested in the documentation:NOTE: Do not specify param or dynamicparam blocks in this script block. These will be injected automatically based on the signature of the command being mocked, and the MockWith script block can contain references to the mocked commands parameter variables.
You're asserting that
{ $DataTable -eq $dataTable }
, you should note that PowerShell is a case-insensitive language,$DataTable
and$dataTable
refer to the same variable in this case. In addition, equality comparison using the-eq
operator won't work to tell if both, the DataTable used as argument for your function and the DataTable created in theBeforeAll
block are the same. In this case you could use[object]::ReferenceEquals
, however you will need to use a different variable name in your test.
In summary, the Pester test that should solve the problem:
InModuleScope 'MyModule' {
Describe 'MyFunction' {
BeforeAll {
$dt = New-Object System.Data.DataTable
$dt.Columns.Add('Column1', [System.String])
$row = $dt.NewRow()
$row['Column1'] = 'Sample Data'
$dt.Rows.Add($row)
# Mock the DataTable creation in MyInternalFunction
Mock New-Object -ParameterFilter { $TypeName -eq 'System.Data.DataTable' } -MockWith { , $dt }
Mock Write-Output {}
Mock MyPipelineFunction {}
}
It 'should call MyPipelineFunction' {
MyFunction
Assert-MockCalled Write-Output -Exactly 1 -Scope It
Assert-MockCalled New-Object -Exactly 1 -Scope It -ParameterFilter {
$TypeName -eq 'System.Data.DataTable'
}
Assert-MockCalled MyPipelineFunction -Exactly 1 -Scope It -ParameterFilter {
[object]::ReferenceEquals($DataTable, $dt)
}
}
}
}
本文标签: Trouble mocking Powershell function with Pester that takes a Pipeline parameterStack Overflow
版权声明:本文标题:Trouble mocking Powershell function with Pester that takes a Pipeline parameter - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741508837a2382484.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
[DataTable]
instances, soMyPipelineFunction
never actually receives a[DataTable]
, but instead 0 or more[DataRow]
objects. Change$dataTable | MyPipelineFunction
toWrite-Output $dataTable -NoEnumerate | MyPipelineFunction
to see the difference. – Mathias R. Jessen Commented Feb 13 at 19:36