pester / Pester

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

Mock Set-PSRepository throws ParameterBindingValidationException on not existing parameter 'Location' #619

Open StefanSchoof opened 7 years ago

StefanSchoof commented 7 years ago

I try to mock Set-PSRepository

Describe "SetPSRepository" {
    Mock Set-PSRepository

    It "Should work" {
        Set-PSRepository -Name "PSGallery" -InstallationPolicy "Trusted"
    }
}

If I run this I get:

 [-] Should work 273ms
   ValidationMetadataException: The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
   ParameterBindingValidationException: Cannot validate argument on parameter 'Location'. The argument is null or empty.
 Provide an argument that is not null or empty, and then try the command again.
   CmdletInvocationException: Cannot validate argument on parameter 'Location'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
   ParameterBindingException: Cannot retrieve the dynamic parameters for the cmdlet. Cannot validate argument on parameter 'Location'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
   at <ScriptBlock>,\SetPSRepository.Tests.ps1:
 line 5

The Set-PSRepository has no Location parameter. Why is there a Location in the stack trace?

splatteredbits commented 7 years ago

I am also having this issue. PowerShell 5, PowerShellGet 1.0.0.1.

dlwyatt commented 7 years ago

The error is bubbling up from Set-PSRepository's dynamicparam block:

            if($moduleSource)
            {
                $providerName = (Get-ProviderName -PSCustomObject $moduleSource)

                $loc = $moduleSource.SourceLocation

                if(Get-Variable -Name SourceLocation -ErrorAction SilentlyContinue)
                {
                    $loc = $SourceLocation
                }

                if(Get-Variable -Name PackageManagementProvider -ErrorAction SilentlyContinue)
                {
                    $providerName = $PackageManagementProvider
                }

                $null = Get-DynamicParameters -Location $loc -PackageManagementProvider ([REF]$providerName)
            }

Apparently there's something different about how Pester sets things up to fetch dynamic parameters, and how things work under normal execution. The if(Get-Variable -Name PackageManagementProvider -ErrorAction SilentlyContinue) part is evaluating to True even though you haven't passed in a value for -SourceLocation.

I'm not sure why their code needs to be that way. Seems like if ($SourceLocation) would be fine, since it's declared as a parameter. (Shouldn't cause any problems even with strict mode, so far as I know.)

I'll see if I can figure something out, but it's possible that this can't be fixed from the Pester side.

dlwyatt commented 7 years ago

It also seems very odd to me that they're assigning the result of Get-DynamicParameters to $null... There's nothing else in that dynamicparam block, which means it's always returning nothing.

cveld commented 3 years ago

I am also having this issue. Versions:

I was able to work around the issue with introducing an additional mock: Mock -CommandName 'Get-PSRepository' -ModuleName 'PowerShellGet'