pester / Pester

Pester is the ubiquitous test and mock framework for PowerShell.
https://pester.dev/
Other
3.08k stars 470 forks source link

Testing internal module functions #1764

Closed toose closed 3 years ago

toose commented 3 years ago

General summary of the issue

Testing internal module functions does not work as expected. When running Invoke-Pester -Script LabModule.Tests.ps1, I'm returned with the error:

[-] LabModule.Private functions.Should test property foo against expected output 216ms (214ms|1ms) CommandNotFoundException: The term 'Get-PrivateStuff' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. at <ScriptBlock>, C:\Project\Modules\PrivateFunctionTest\LabModule.Tests.ps1:6

In v4, this was solved by using InModuleScope which AFAIK should be avoided in v5.

Describe your environment

Pester version : 5.0.4 C:\Program Files\WindowsPowerShell\Modules\Pester\5.0.4\Pester.psm1 PowerShell version : 5.1.19041.546 OS version : Microsoft Windows NT 10.0.19041.0

Steps to reproduce

Example script files divided into scriptblocks:

#region LabModule.psd1
@{
    RootModule = 'LabModule.psm1'
    ModuleVersion = '1.0'
    GUID = 'd00578f5-fb6b-4c47-83fb-ed1c8d9a1ec2'
    FunctionsToExport = 'Get-PublicStuff'
}

#region LabModule.psm1
# public function
function Get-PublicStuff {
    # Does something
}
# private function
function Get-PrivateStuff {
    return [PSCustomObject] @{ foo ='Cactus' }
}
#endregion

#region LabModule.tests.ps1
Import-Module .\LabModule.psd1 -Force

Describe "LabModule" {
    Context "Private functions" {
        It "Should test property foo against expected output" {
            $stuff = Get-PrivateStuff
            $stuff.foo | Should -Be 'Cactus'
        }
    }
}
#endregion

Now run Invoke-Pester .\LabModule.Tests.ps1 -Ouptut Detailed

Expected Behavior

Execute assertions against an private internal module function.

Current Behavior

CommandNotFoundException is raised.

fflaten commented 3 years ago

The general advice is to avoid InModuleScope when possible. When it's used it'd be smart to limit it to calls inside a It. This doesn't mean it's banned as it's still critical for testing internal functions like you're doing in this case.

See https://pester.dev/docs/usage/modules which was newly updated with Pester v5 examples using InModuleScope for exactly this use case.

toose commented 3 years ago

Thanks @fflaten. I'll keep that in mind, but I think was over engineering the solution. Seeing as these are unit tests I'm writing, I get the desired behavior if I dot source the private function in BeforeAll and then test against it.