Search code examples
powershellmockingpester

How to mock a script that is dot sourced?


We're trying to figure out how to mock a dot sourced script in Pester.

Script1.ps1

$Import = @('Script 1 data')

. 'C:\Script2.ps1' -JobName 'Script 2 data'

$Import

Script2.ps1

Param (
    [String]$JobName
)

$Import += $JobName

Output

Script 1 data
Script 2 data

In the example above Script2.ps1 is already tested in a separate Pester test file (Script2.Tests.ps1). For the testing of Script1.ps1 we only have a need to asses if the other script is called or not.

In Script1.ps1 we explicitly use dot sourcing to make sure that the changed/updated variables come back in the current scope.

An approach would be to use a Function with the sole purpose of calling Script2.ps1 that can then be easily mocked. However, in that case the variable modifications are stuck in the function scope.

What is the best way to assess if the script has been called and still make sure the variables come back in the current scope?


Solution

  • Well, you have the Return keyword that you can use to send data across scopes in your case. You can use Return inside the function you talked about or Script2.ps1 itself. You do not need to modify your variable in another script. Instead, pass it the value, modify it locally in Script2, Return it to Script1 where you grab the modified value.

    Script1

    $Import = @('Script 1 data')
    
    $ModValue = . 'C:\Script2.ps1' -JobName 'Script 2 data'
    
    $Import += $ModValue
    $Import
    

    Script2

    Param (
        [String]$JobName
    )
    #do what you need to do here
    $modifiedvalue = $JobName #For the sake of demo i am doing this.
    
    Return $modifiedvalue #Where $modifiedvalue is what you want to send back to script1
    

    Output

    Script 1 data
    Script 2 data
    

    You can add errorhandling in script2 if you expect it and return error messages to Script1 as well. Checking the value of $ModValue in that case can give you better control on understanding what happens in script2.

    Param (
        [String]$JobName
    )
    
    try
    {
        #do what you need to do here
        $modifiedvalue = $JobName #For the sake of demo
    
        Return $modifiedvalue #Where $modifiedvalue is what you want to send back to script1
    }
    catch
    {
        Return $_.Exception.Message
    }