I would like to know if it is possible to Mock the same cmdlet in a function that return different object data types?
Below shows the function that has Get-ADGroupMember
cmdlet appearing 2 times. I would like both Get-ADGroupMember
to return different objects & data types using Mock
cmdlet.
I am expecting to have the first Get-ADGroupMember
to return a System.Array
object type & the second Get-ADGroupMember
to return a PSCustomObject
type.
Thanks in advance for helping.
I have tried to Mock the cmdlet using what I have researched from the web & Pester documentation but has found no success.
BeforeAll {
function Get-Something
{
## Initialize an array for PSCustomObject
$ArrayCustomObject = @()
## Return an Array Object
$ArrayObject = (Get-ADGroupMember "AD_Group_Name").SamAccountName
foreach ($Object in $ArrayObject)
{
## Return a PSCustomObject + SamAccountName is not the same as the previous SamAccountName
$PSCustomObject = Get-ADGroupMember $ADMember | Select-Object objectClass, SamAccountName
$ArrayCustomObject += $PSCustomObject
}
return $ArrayCustomObject
}
}
Describe "Get-Something" {
Context "MOCK Get-ADGroupMember" {
BeforeAll {
## Would like to have the first cmdlet to be mock with this
Mock -CommandName Get-ADGroupMember -MockWith {
[PSCustomObject]@{SamAccountName = "AD_GROUP_1"},
[PSCustomObject]@{SamAccountName = "AD_GROUP_2"}
}
## Would like to have the second cmdlet to be mock with this
Mock -CommandName Get-ADGroupMember -MockWith {
[PSCustomObject]@{objectClass = "User"; SamAccountName = "USER_1"},
[PSCustomObject]@{objectClass = "User"; SamAccountName = "USER_2"}
}
}
It "Get-ADGroupMember should run 2 times" {
Get-Something -ADGroupName "ANY_AD_NAME"
Assert-MockCalled Get-ADGroupMember -Times 2
}
It "Should Match PSCustomObject" {
(Get-Something -ADGroupName "ANY_AD_NAME").count | should -be 2
}
}
}
Here is the result:
Describing Get-Something
Context MOCK Get-ADGroupMember
[+] Get-ADGroupMember should run 2 times 25ms (22ms|3ms)
[-] Should Match PSCustomObject 13ms (12ms|0ms)
Expected 2, but got 4.
Tests completed in 137ms
Tests Passed: 1, Failed: 1, Skipped: 0 NotRun: 0
You can use -ParameterFilter
on a Mock
to scope it to a specific use of a cmdlet based on the parameters used with it. In your example we can make a Mock match just the first use of Get-ADGroupMember
by having a parameter filter that checks $Identity
is set to "AD_Group_Name". The other Mock
we then don't use a Parameter Filter on and it will get used for the other usage.
The following works (note I had to declare Get-ADGroupMember
as a function in my example because I don't have that Module installed on my system at the moment):
BeforeAll {
function Get-ADGroupMember {
param($Identity)
}
function Get-Something {
## Initialize an array for PSCustomObject
$ArrayCustomObject = @()
## Return an Array Object
$ArrayObject = (Get-ADGroupMember "AD_Group_Name").SamAccountName
foreach ($Object in $ArrayObject) {
## Return a PSCustomObject + SamAccountName is not the same as the previous SamAccountName
$PSCustomObject = Get-ADGroupMember $ADMember | Select-Object objectClass, SamAccountName
$ArrayCustomObject += $PSCustomObject
}
return $ArrayCustomObject
}
}
Describe "Get-Something" {
Context "MOCK Get-ADGroupMember" {
BeforeAll {
Mock -CommandName Get-ADGroupMember -ParameterFilter { $Identity -eq 'AD_Group_Name' } -MockWith {
[PSCustomObject]@{SamAccountName = "AD_GROUP_1" },
[PSCustomObject]@{SamAccountName = "AD_GROUP_2" }
}
Mock -CommandName Get-ADGroupMember -MockWith {
[PSCustomObject]@{objectClass = "User"; SamAccountName = "USER_1" },
[PSCustomObject]@{objectClass = "User"; SamAccountName = "USER_2" }
}
}
It "Get-ADGroupMember should run 3 times" {
Get-Something -ADGroupName "ANY_AD_NAME"
Assert-MockCalled Get-ADGroupMember -Times 3
}
It "Should Match PSCustomObject" {
$Result = (Get-Something -ADGroupName "ANY_AD_NAME")
$Result.count | should -be 4
$Result.objectClass | Should -Contain 'User'
}
}
}
Also I changed the checks of your test. We expect Get-ADGroupMember
to run 3 times, once outside the loop (where it returns 2 results) then twice in the loop (once for each result). And we expect the Count
returned to be 4, because each time its called in the loop it returns 2 results, so 4 total. I added a further check to make sure we're getting the objectClass
property at the end to prove the right Mock was being called.