Pester icon indicating copy to clipboard operation
Pester copied to clipboard

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

Open StefanSchoof opened this issue 9 years ago • 7 comments

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?

StefanSchoof avatar Oct 11 '16 09:10 StefanSchoof

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

splatteredbits avatar Mar 21 '17 00:03 splatteredbits

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 avatar Mar 21 '17 01:03 dlwyatt

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.

dlwyatt avatar Mar 21 '17 01:03 dlwyatt

I am also having this issue. Versions:

  • PowerShell 7.0.3
  • Pester 5.0.4
  • PowerShellGet 2.2.4.1
  • WSL2
  • Windows 10.0.19041

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

cveld avatar Oct 19 '20 18:10 cveld

I'm also having this problem mocking Set-PSRepository.

Operating environment:

PowerShell 5.1.22621.4391 Pester 5.6.1 PowerShellGet 1.0.0.1 Windows 10.0.22631 (Windows 11)

The error message I saw was:

System.Management.Automation.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.

When I stepped through the code it stepped into Pester.psm1. This is the line it failed on:

image

(the return line in function Get-DynamicParametersForMockedFunction)

$Parameters is set to:

Key                Value    
---                -----    
Name               PSGallery
InstallationPolicy Trusted 

and $DynamicParamScriptBlock is set to the following code:

	[CmdletBinding(PositionalBinding=$false, HelpUri='https://go.microsoft.com/fwlink/?LinkID=517128')]
	param(
	[object] ${P S Cmdlet},

	[ValidateNotNullOrEmpty()]
	[string]
	${Name},

	[ValidateNotNullOrEmpty()]
	[uri]
	${SourceLocation},

	[ValidateNotNullOrEmpty()]
	[uri]
	${PublishLocation},

	[ValidateNotNullOrEmpty()]
	[uri]
	${ScriptSourceLocation},

	[ValidateNotNullOrEmpty()]
	[uri]
	${ScriptPublishLocation},

	[pscredential]
	[System.Management.Automation.CredentialAttribute()]
	${Credential},

	[ValidateSet('Trusted','Untrusted')]
	[string]
	${InstallationPolicy},

	[ValidateNotNullOrEmpty()]
	[uri]
	${Proxy},

	[pscredential]
	[System.Management.Automation.CredentialAttribute()]
	${ProxyCredential},

	[ValidateNotNullOrEmpty()]
	[string]
	${PackageManagementProvider}
)

$PSCmdlet = ${P S Cmdlet}
 
if (Get-Variable -Name Name -ErrorAction SilentlyContinue)
{
	$moduleSource = Get-PSRepository -Name $Name -ErrorAction SilentlyContinue -WarningAction SilentlyContinue

	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)
	}
}

I stepped through this code. $loc was set to $SourceLocation, which was set to $null. It threw the exception on the final line, $null = Get-DynamicParameters ...

I'm guessing @cveld's workaround works by mocking Get-PSRepository to return nothing, so the if($moduleSource) {...} block doesn't run. However, it didn't work for me.

SimonEData avatar Dec 20 '24 12:12 SimonEData

Looks like this is still an issue 9 years later

akzov avatar Jul 09 '25 04:07 akzov

Can see it on main as well:

invoke-pester -container (
    New-PesterContainer -ScriptBlock {
        Describe "d" { 
            It "i" { 
                Mock Set-PSrepository {}
                
                Set-PSRepository -Name "PSGallery" -InstallationPolicy "Trusted" -Location "l" 
            } 
        }
    }
)

nohwnd avatar Jul 09 '25 07:07 nohwnd