2

I have question regarding to the mocking mechanism in Pester. I have a script Script.ps1 that I want to test. The tests are located in Script.Tests.ps1. In Script.ps1 I implemented the following function:

function Start-Executable {
    param([string]$Executable)

    Start-Process $Executable
}

For testing purpose I want to mock Start-Process. The Script.Tests.ps1 contains the following test.

BeforeAll{
   . $PSScriptRoot/Script.ps1
}

Describe 'Start-Executable' {
    Mock -CommandName 'Start-Process' -MockWith {return $null}
    
    It 'Start-Process is called.'{

       Start-Executable -Executable 'Test.exe'
       Assert-MockCalled 'Start-Process'
    }
}

If I execute the test, the real Start-Process throws an exception that 'Test.exe' could not be found. If I move the mock in the It-block, the test passes. I would like to add the mock in the Describe-block (or later, as more tests are getting written, in the Context-block) to have one mock covering a bench of tests. Is this possible and what I am doing wrong?

Mark Wragg
  • 22,105
  • 7
  • 39
  • 68
dhelfer
  • 23
  • 2

1 Answers1

2

It looks like you're probably using Pester v5. As such your mock needs to be in a BeforeAll or BeforeEach block.

This should work:

BeforeAll{
   . $PSScriptRoot/Script.ps1
}

Describe 'Start-Executable' {
    BeforeAll {
        Mock -CommandName 'Start-Process' -MockWith {return $null}
    }

    It 'Start-Process is called.'{

       Start-Executable -Executable 'Test.exe'
       Assert-MockCalled 'Start-Process'
    }
}

All code placed in the body of Describe outside of It, BeforeAll, BeforeEach, AfterAll, AfterEach will run during discovery and it's state might or might not be available to the test code, see Discovery and Run

-- https://pester-docs.netlify.app/docs/migrations/breaking-changes-in-v5

Mark Wragg
  • 22,105
  • 7
  • 39
  • 68
  • If I want to add a second mock, must it be placed also in the BeforeAll block? – dhelfer Feb 25 '22 at 11:29
  • Yes. But if you want to Mock the same command in different ways you can define them inside separate `BeforeAll` blocks inside different `Context` blocks. Another way to make different Mocks fire for different circumstances is to use a ParameterFilter so a Mock is only matched if the command is invoked with a certain set of parameters. – Mark Wragg Feb 25 '22 at 12:02