Pester
Pester copied to clipboard
Mocking cmdlet with dynamic parameters not working
Hey,
I am trying to use an azure-commandlet which uses dynamic parameters. The commandlet is new-azureresourcegroupdeployment. I am mocking it in the following way
Mock New-AzureResourceGroupDeployment { throw "No appropriate mock called for New-AzureResourceGroupDeployment" }
Mock New-AzureResourceGroupDeployment -MockWith { return $validResourceGroupDeployment } -ParameterFilter{$Name -eq $validResourceGroupName -and $ResourceGroupName -eq $validResourceGroupName -and $TemplateFile -eq $validTemplatePath}
But when I run my tests, I get the exception:
Cannot retrieve the dynamic parameters for the cmdlet. Exception calling "GetDynamicParameters" with "0" argument(s): "Object reference not set to an instance of an object
Am I missing something. Could you please point me to an example where you have mocked a commandlet which has dynamic parameters. I was using the 3.3.6 version. I upgraded to 3.3.8 and tried again but was not successful.
Thanks
I'll take a look at this later today when I have time. There have been a couple of instances of weird cmdlets that break the dynamic parameter mocking code (such as the AD module). Could be that there's something new happening in these Azure cmdlets that I need to support in Pester.
Thanks dave. That would be helpful
I haven't been able to reproduce this yet. This code doesn't give me the error you reported:
Describe 'Test' {
Mock New-AzureResourceGroupDeployment { throw "No appropriate mock called for New-AzureResourceGroupDeployment" }
It 'Works' {
{ New-AzureResourceGroupDeployment -ResourceGroupName Test } | Should Throw
}
}
I tested this with the latest version of the Azure module, which was just released.
In the code you posted, you had a second version of the mock with a parameter filter, but the variables that the mock depends on were not included. If you can provide the values that you were assigning to those variables, I can try to run that version of the mock and see if it fails.
I mocked the command with a parameter filter as well; still no problems, using the latest AzureResourceManager module and Pester 3.3.8.
In my case the New-AzureResourceGroupDeployment cmdlet is used inside a function. And I am writing tests against that function mocking the behavior of the azure cmdlet. Would that make a difference?
No, that shouldn't matter.
Hi @dlwyatt, I think I'm encountering this same problem. And I think I have a repro:
Get-Command New-AzureRmResourceGroupDeployment | % ModuleName
[string](Get-Module AzureRM.Resources).Version
Write-Host Pester
[string](Get-Module Pester).Version
Describe 'Describe' {
Mock New-AzureRmResourceGroupDeployment
It 'this throws Exception calling "GetDynamicParameters"' {
New-AzureRmResourceGroupDeployment -ResourceGroupName Test -TemplateFile Test
}
}
which yields

Are you able to reproduce this problem on your machine?
@alx9r that's the exact issue I'm seeing except I have Pester 3.4.0 The AzureRM.Resources module is 3.0.1, same as yours
@dlwyatt - I've got a Mock from AzureRM.Profiles for Add-AzureRmAccount that works fine but New-AzureRmResourceGroupDeployment cmdlet won't mock. I've tried both "Mock -ModuleName" & "InModuleScope -ModuleName" syntax with the same result. I haven't tried any other cmdlets yet
I'm running into this problem now too.
I'm running into this as well. I'm on 3.4.4. I'm receiving this error using the same command as referenced here. However, it has worked. I'm not sure what state I have to get this into to repro it. I'm using the latest AzureRM module (3.3.0) as well.
I don't think this is Pester-version-dependent. I'm seeing the following results:
3.0.0,3.0.1,3.0.1.1-- no error3.0.2and later -- error
Mocking dynamic parameters seems to have been implemented between 3.0.1.1 and 3.0.2.
Here is the repro code I'm using. It checks out each Pester version starting at 3.0.0 and tries to mock New-AzureRmResourceGroupDeployment.
I have gotten it to work in 3.4.4. However, I'm unsure what state it was in when it did work.
On Thu, Jan 12, 2017 at 5:07 PM, alx9r [email protected] wrote:
I don't think this is Pester-version-dependent. I'm seeing the following results:
- 3.0.0, 3.0.1, 3.0.1.1 -- no error
- 3.0.2 and later -- error
Mocking dynamic parameters seems to have been implemented between 3.0.1.1 and 3.0.2 https://github.com/pester/Pester/compare/3.0.1.1...3.0.2.
Here is the repro code https://gist.github.com/alx9r/7749f3a0657941d0b5839128dcf19feb I'm using. It checks out each Pester version starting at 3.0.0 and tries to mock New-AzureRmResourceGroupDeployment.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pester/Pester/issues/339#issuecomment-272312788, or mute the thread https://github.com/notifications/unsubscribe-auth/AEG3-uPiBiTUIzk7fEvWVPl5De2PITUrks5rRrIlgaJpZM4EMnAx .
I'm encountering this issue with Pester 4.3.1 and PackageManagement\Get-PackageSource
Here's a simple repro:
PS> New-Module -Name 'MockTest' -ScriptBlock {
function Get-ThosePackageSources {
Get-PackageSource -ProviderName 'NuGet' -ConfigFile $Env:APPDATA\NuGet\nuget.config
}
}
PS> Describe 'Get-ThosePackageSources' {
Mock Get-PackageSource -Module PackageManagement -MockWith {
throw [System.NotImplementedException]::new('No mock yet')
} -Verifiable
It 'should invoke our Mock' {
$null = Get-ThosePackageSources
Assert-VerifiableMock
}
}
edit: This repro is incorrect, Get-PackageSource is called in the incorrect scope, see below.
~Here is even simpler repro. The Mock is not called.~
Import-Module PackageManagement
Describe 'Get-PackageSource' {
It 'should invoke our Mock' {
Mock Get-PackageSource -Module PackageManagement
Get-PackageSource
Assert-MockCalled Get-PackageSource -Module PackageManagement
}
}
Describing Get-PackageSource
[-] should invoke our Mock 37ms
Expected Get-PackageSource in module PackageManagement to be called at least 1 times but was called 0 times
7: Assert-MockCalled Get-PackageSource -Module PackageManagement
@nohwnd Is your last example valid? By using the -Module switch (I suppose you were meaning -ModuleName there), the mock you should apply to function calls within the PackageManagement module context, which is not the case in the test.
Am I missing something there?
@renehernandez does it not work? -Module should be the same as using -ModuleName, because it will resolve to -ModuleName, unless there is an ambiguous parameter in the function. I don't think there is such parameter because the output is from the command directly. So the repro should be correct.
@nohwnd The parameter thing was just a side topic :). My main question is: By using -Module or -ModuleName, we are saying that we want to mock the calls inside the module, right? But then, in the example, we are calling Get-PackageSource at the script scope, which it's different that the PackageManagement module scope.
You are right, that mock is defined within the module but outside of the module it still binds to the cmdlet not the alias so the original command is called and not the mock. So the error correctly reports that the mock was not called.
This came up again when I was working with New-AzResourceGroupDeployment. I am looking for various ways around this error, and perhaps can update documentation or point to link for fix? Gathering some information here.
When mocking New-AzResourceGroupDeployment and passing in custom parameters for the ARM template, the Pester 5 mock function does not discover the dynamic parameters. Since dynamic parameters are only available at runtime and not compile time, these are not discoverable. This results in following error:
Mock New-AzResourceGroupDeployment -MockWith ''
Cannot retrieve the dynamic parameters for the cmdlet
I think @renehernandez was working on this and put in a PR for Pester 5 which may have been rolled back? I couldn't find a good example to address this, so might make sense to update the error message to include an example if verbosity turned up, or provide path to fix.
I'd prefer not to ignore the module validation checker in Pester and extend to check those parameters I specify in the mock.
In this example, $adUserId and $secretValue are custom parameters, not defined explicitly in the code for the cmdlet.
$outputs = New-AzResourceGroupDeployment `
-WhatIf `
-SkipTemplateParameterPrompt `
-DeploymentName $deploymentName `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateFile `
-TemplateParameterFile $TemplateParameterFile `
-adUserId $adUserId `
-secretValue $secretValue `
-DeploymentDebugLogLevel All -Verbose `
I found some related items here. https://github.com/pester/Pester/pull/1317 https://github.com/pester/Pester/issues/1308 https://gordon.byers.me/azure/templateparameterobject-parameter-azurermresourcegroupdeployment/ https://github.com/MicrosoftDocs/feedback/issues/3073 https://github.com/Azure/azure-powershell/issues/7980 https://github.com/Azure/azure-powershell/issues/4186
Source for the cmdlet, related articles and some potential bugs people may hit. https://github.com/Azure/azure-powershell/blob/56b4197ff38c83ba8d8c240b0e23cbbe39c4305a/src/Resources/ResourceManager/Implementation/ResourceGroupDeployments/NewAzureResourceGroupDeploymentCmdlet.cs https://github.com/Azure/azure-powershell/issues/1528
In the cmdlet, there is (or was?) an option for passing in a TemplateParameterObject. I think I used that to get around this issue last time. It's mentioned recently. https://github.com/Azure/azure-powershell/issues/14170
It would be great if mock could enable extending the success of discovery to include parameters we specify with their types, if this feature isn't already in place.