This PowerShell function identifies files which do not contain a particular string:
function GetFilesLackingItem([string]$pattern)
{
Get-ChildItem | ? { !( Select-String -pattern $pattern -path $_ ) }
}
I am attempting to write a Pester unit test by mocking Get-ChildItem and Select-String but ran into an issue. Here are two attempts that both fail in the same way. The first test uses Mock's parameterFilter
to differentiate, whereas the second test adds logic to do this in the mockCommand
itself.
Describe "Tests" {
$fileList = "nameA", "nameB", "nameC", "nameD", "nameE" | % {
[pscustomobject]@{ FullName = $_; }
}
$filter = '(B|D|E)$'
Mock Get-ChildItem { return $fileList }
It "reports files that did not return a match" {
Mock Select-String { "matches found" } -param { $Path -match $filter }
Mock Select-String
$result = Get-ChildItem | ? { !(Select-String -pattern "any" -path $_) }
$result[0].FullName | Should Be "nameA"
$result[1].FullName | Should Be "nameC"
$result.Count | Should Be 2
}
It "reports files that did not return a match" {
Mock Select-String {
if ($Path -match $filter) { "matches found" } else { "" }
}
$result = Get-ChildItem | ? { !(Select-String -pattern "any" -path $_ ) }
$result[0].FullName | Should Be "nameA"
$result[1].FullName | Should Be "nameC"
$result.Count | Should Be 2
}
}
If I modify the tests such that the Select-String -path
parameter is $_.FullName
instead of $_
then both tests pass. But in real life (i.e. if I run the line without mocks) it works correctly with just $_
. (It also works correctly with $_.FullName
.) So the real Select-String seems able to map FullName from an array of FileInfo objects for the Path parameter (though I could not find that there was a parameter alias to do that).
My question: is it possible to leave the original code as is, i.e. leave the Path parameter as $_
on the line under test, and modify the Select-String mock instead to extract the FullName property? Trying for example, $Path.FullName
in either mock does not work.