I'm using Pester to unit test some code I've written. In the tests I mock Test-Path
using a parameter filter:
Mock -CommandName 'Test-Path' -MockWith { return $false } `
-ParameterFilter { $LiteralPath -and $LiteralPath -eq 'c:\dummy.txt' }
The following is psuedo code for what I'm doing:
If ( Test-Path -LiteralPath c:\dummy.txt )
{
return "Exists"
}
else
{
Attempt to get file
If ( Test-Path -LiteralPath c:\dummy.txt )
{
return "File obtained"
}
}
On the first call to Test-Path
I want to return $false
and on the second call I want to return $true
. I can think of a couple of ways of achieving this, but they don't feel right:
On the first call use the Path
parameter and on the second use LiteralPath
. Have two mocks one with a ParameterFilter
for each. I don't like the idea of hacking the code in order to facilitate a test.
Create a function with parameters for: Path
and InstanceNumber
. Create mocks for the function. This is better than the above, but I don't like the idea of having a parameter just for testing purposes.
I've looked and can't find a way to mock based on the nth call. Does Pester facilitate this and I've just missed it? If not is there a cleaner way of achieving what I want?
function Test-File{
If ( Test-Path -LiteralPath c:\dummy.txt )
{
return "Exists"
}
else
{
If ( Test-Path -LiteralPath c:\dummy.txt )
{
return "File obtained"
}
}
}
Describe "testing files" {
it "file existence test" {
#Arrange
$script:mockCalled = 0
$mockTestPath = {
$script:mockCalled++
if($script:mockCalled -eq 1)
{
return $false
}
else
{
return $true
}
}
Mock -CommandName Test-Path -MockWith $mockTestPath
#Act
$callResult = Test-File
#Assert
$script:mockCalled | Should Be 2
$callResult | Should Be "File obtained"
Assert-MockCalled Test-Path -Times $script:mockCalled -ParameterFilter { $LiteralPath -and $LiteralPath -eq 'c:\dummy.txt' }
}
}
I think you are after this?! let me know if not!