diff --git a/src/functions/Mock.ps1 b/src/functions/Mock.ps1 index 92bf2b7d8..35fe021d8 100644 --- a/src/functions/Mock.ps1 +++ b/src/functions/Mock.ps1 @@ -82,6 +82,14 @@ function Create-MockHook ($contextInfo, $InvokeMockCallback) { if ($cmdletBinding -ne '[CmdletBinding()]') { $cmdletBinding = $cmdletBinding.Insert($cmdletBinding.Length - 2, ',') } + # When the cmdlet has no explicit DefaultParameterSetName and its dynamic parameters + # introduce multiple named parameter sets, PowerShell cannot resolve which set applies + # when the mock is called without arguments. Injecting '__AllParameterSets' as the + # default makes the no-argument call succeed, matching the real cmdlet's behaviour. (#1531) + if ([string]::IsNullOrEmpty($metadata.DefaultParameterSetName)) { + $cmdletBinding = $cmdletBinding.Insert($cmdletBinding.Length - 2, "DefaultParameterSetName='__AllParameterSets'") + $cmdletBinding = $cmdletBinding.Insert($cmdletBinding.Length - 2, ',') + } $cmdletBinding = $cmdletBinding.Insert($cmdletBinding.Length - 2, 'PositionalBinding=$false') } diff --git a/tst/functions/Mock.Tests.ps1 b/tst/functions/Mock.Tests.ps1 index c3c60f954..2192255eb 100644 --- a/tst/functions/Mock.Tests.ps1 +++ b/tst/functions/Mock.Tests.ps1 @@ -2027,6 +2027,23 @@ Describe 'Mocking commands with potentially ambiguous parameter sets' { } } +Describe 'Mocking a cmdlet with multiple non-default parameter sets and no DefaultParameterSetName (#1531)' { + # Get-PackageSource has two provider-specific parameter sets (NuGet and PowerShellGet) with no + # default, and its dynamic parameters introduce those sets. Without a DefaultParameterSetName in + # the generated bootstrap proxy, PowerShell cannot resolve the parameter set when the mock is + # called with no arguments, producing "Parameter set cannot be resolved". The fix injects + # DefaultParameterSetName='__AllParameterSets' into the proxy [CmdletBinding()] for any cmdlet + # whose metadata has an empty DefaultParameterSetName. + + It 'Can mock Get-PackageSource and call it with no arguments' -Skip:($null -eq (Get-Command Get-PackageSource -ErrorAction SilentlyContinue)) { + Mock Get-PackageSource { [PSCustomObject]@{ Name = 'MockedSource'; ProviderName = 'NuGet' } } + + $result = Get-PackageSource + $result.Name | Should -Be 'MockedSource' + Should -Invoke Get-PackageSource -Times 1 + } +} + Describe 'When mocking a command that has an ArgumentList parameter with validation' { BeforeAll { Mock Start-Process { return 'mocked' }