Author Posts

April 20, 2018 at 5:17 pm

Hi everyone,

I am testing my self-made PS module and when the PS module gets imported, there is a script that gets dot-sourced to setup the environment prior to loading the module. There is a variable that gets defined during the environment set up and gets utilized in one of my functions within the module.

Now with that explained, when I run my Pester test, I can see that the variable is null due to my verbose logging even though my verbose logging shows that the script is dot-sourced and loaded prior to executing the test.

Now if I set the variable to a Global variable, then my test works because the variable is now defined. I do not want to setup my variable to a Global scope if it is not necessary.

Any suggestions on what I need to do to prevent from changing my variable to a Global defined variable or best practice?

Thanks,
Michael

April 20, 2018 at 7:18 pm

Could you provide some code examples and how you've got your Pester test set up?

April 20, 2018 at 8:28 pm

Hi Adam,

First I must say that I am fan of your work and I also purchased your Pester book on leanpub. It was a great read and I try to adopt many of the things I learned from there. However, I am still a beginner with it comes to Pester testing. Thank you for that great book.

Now, back to business. I didn't provide you with my actual code, due to the fear of accidentally adding something here that shouldn't be on the web. But the below snippets should show you what I am running into.

# this is within my module manifest
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
ScriptsToProcess = '.\SetupEnvironment.ps1'
# within setupEnvironment.ps1 I have a few things happening, but depending on certain dependancies
# the variable value could be blah or foo, but the variable is always defined otherwise an error throws 
# and the module doesn't get imported. 
...
$message = "foo"
...
# function within my module
function Get-Message {
# the variable that is defined in my setupenvironment.ps1 script  
if($message)
  {
    $obj = [pscustomObject] @{
           Message = $message
          }
    return $obj
  }
}
# within my Pester test
# I have also tried to dot-source the setupEnvironment.ps1 file here to but that didn't seem to help me out any
Import-Module MyModule -Force

InModuleScope MyModule {
    Describe "Get-Message" {
      it 'should return a object' {
        $result = Get-Message

        $result.Message | Should be "foo" 
        # however this is going to fail, because no object gets returned because $message is $null
      }
    }
}

I hope this is a good enough example. Let me know if you have any further questions.

Thanks,
Michael

April 21, 2018 at 12:14 am

Hello! Would/could you consider defining $message a different way?

First, remove the SetupEnvironment.ps1, or at least comment out the line of the variable. Then,

# PSD1 file

# Script module or binary module file associated with this manifest.
RootModule = 'MyModule.psm1'
# PSM1 file

$script:message = 'foo'

This works for your function and your test, and is a pretty common "module scope" practice. (Available to the module but obscured from the end user, the same way a private function behaves.)

April 22, 2018 at 1:41 pm

I would honestly leave it in the global scope. It's not going to force you to re-architect your process and it's not necessarily "bad" to do. If you're concerned with leaving the global variable hanging around, you could put $MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { Remove-Variable -Name message -Scope Global } in your module to ensure it gets removed when your module is unloaded.

Otherwise, I agree with Brian.