I have some old Pester v4 tests that are failing when I try to run them in Pester v5.
With Pester v4 I read that once Mock is called it will continue to apply for the rest of the Describe block, even if it was called within an It block. So I would call it from the Describe block, outside of an It block, to make it obvious it didn't just apply to a single It block.
That behaviour which worked in Pester v4 doesn't seem to work in Pester v5.
This is the script I'm writing tests against, MyScriptToTest.ps1:
function Get-FirstText ()
{
return 'Some text'
}
function Get-SecondText ()
{
return 'Other text'
}
function Get-Text ()
{
$a = Get-FirstText
$b = Get-SecondText
return "$a; $b"
}
And here are the tests, in MyScriptToTest.Tests.ps1:
BeforeAll {
. (Join-Path $PSScriptRoot 'MyScriptToTest.ps1')
}
Describe 'Get-FirstText' {
It 'returns text "Some text"' {
$result = Get-FirstText
$result | Should -Be 'Some text'
}
}
Describe 'Get-Text' {
It 'returns text "Some text; Other text"' {
Get-Text | Should -Be 'Some text; Other text'
}
Mock Get-FirstText { return 'Mock text' }
It 'returns text "Mock text; Other text" after mocking Get-FirstText' {
Get-Text | Should -Be 'Mock text; Other text'
}
}
The Pester v5 test output is as follows:
Describing Get-FirstText
[+] returns text "Some text" when called indirectly 13ms (8ms|5ms)
Describing Get-Text
[+] returns text "Some text; Other text" 66ms (54ms|13ms)
[-] returns text "Mock text; Other text" after mocking Get-FirstText 42ms (41ms|1ms)
Expected strings to be the same, but they were different.
String lengths are both 21.
Strings differ at index 0.
Expected: 'Mock text; Other text'
But was: 'Some text; Other text'
^
at Get-Text | Should -Be 'Mock text; Other text', C:\...\MyScriptToTest.Tests.ps1:20
at <ScriptBlock>, C:\...\MyScriptToTest.Tests.ps1:20
Tests completed in 565ms
Tests Passed: 2, Failed: 1, Skipped: 0 NotRun: 0
However, if I move the Mock command into the It block then it works:
BeforeAll {
. (Join-Path $PSScriptRoot 'MyScriptToTest.ps1')
}
Describe 'Get-FirstText' {
It 'returns text "Some text"' {
$result = Get-FirstText
$result | Should -Be 'Some text'
}
}
Describe 'Get-Text' {
It 'returns text "Some text; Other text"' {
Get-Text | Should -Be 'Some text; Other text'
}
It 'returns text "Mock text; Other text" after mocking Get-FirstText' {
Mock Get-FirstText { return 'Mock text' }
Get-Text | Should -Be 'Mock text; Other text'
}
}
I haven't figured out the new constraints around calling the Mock command in Pester v5. Can the Mock command still be called within a Describe or Context block, outside of an It block? Or does it now always have to be called within an It block?
The docs describe the v5+ change of where
Mockcommands must (now) be placed (emphasis added):That is, a
Mockcommand placed directly insideDescribeorContextcommands - as in the code in your question - is now effectively ignored.To spell it out: In Pester v5+, for a
Mockstatement to be effective, it must be placed inside one of the following constructs:Inside a
BeforeAllcommand, which therefore applies to all tests in the same scope.BeforeAllcommand may be placed directly inside aDescribecommand or - for more fine-grained control - inside a nestedContextcommand.Inside an individual
Itcommand, in which case it applies to that test only.In the context of your code, this means:
Context-levelMock:It-levelMock: