Mock Set-PSRepository throws ParameterBindingValidationException on not existing parameter 'Location'
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?
I am also having this issue. PowerShell 5, PowerShellGet 1.0.0.1.
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.
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.
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'
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:
(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.
Looks like this is still an issue 9 years later
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"
}
}
}
)