1

I'm pretty new to Pester so please bear with me. We're trying to make tests for a very large script that does some active directory queries and validates data. I've simplified it a bit to the following example:

Dummy.ps1

Param (
    [String]$OU,
    [String[]]$Groups
)

$AllOUusers = Get-ADUser -Filter * -SearchBase $OU

$GroupMemberUsers = foreach ($G in $Groups) {
    Get-ADGroupMember $G -Recursive | Get-ADUser -Properties whenCreated    
}

Dummy.Tests.ps1

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'

$Params = @{
    OU = 'OU=users,DC=contoso,DC=com'
    Groups = 'Group1', 'Group2'
}

Describe 'test' {
    Mock Get-ADGroupMember {
        [PSCustomObject]@{SamAccountName = 'Member1'}
        [PSCustomObject]@{SamAccountName = 'Member2'}
    }
    Mock Get-ADUser {
        [PSCustomObject]@{SamAccountName = 'User1'}
        [PSCustomObject]@{SamAccountName = 'User2'}
        [PSCustomObject]@{SamAccountName = 'User3'}
    }
    Mock Get-ADUser {
        [PSCustomObject]@{SamAccountName = 'User4'}
        [PSCustomObject]@{SamAccountName = 'User5'}
    } -ParameterFilter {$identity -eq 'User1'}

    ."$here\$sut" @Params

    it 'test 1' {
        ($AllOUusers | Measure-Object).Count | Should -BeExactly 3
    }
    it 'test 2' {
        ($GroupMemberUsers | Measure-Object).Count | Should -BeExactly 2
        'User4', 'User5' | Should -BeIn $GroupMemberUsers.SamAccountName
    }
}

Error:

Cannot validate argument on parameter 'Identity'.

In the case above we're trying to collect in the first place all user accounts in a specific OU and afterwards all the members of a specific security group. When we have the members we use the Get-ADUser CmdLet again to get more details for these specific members.

The end goal is to have a Mock for the first Get-ADUser that returns all the user accounts, and a second Mock of Get-ADUser that only returns a specific set of user accounts based on group membership (or simulated group membership).

System details

  • PowerShell 5.1
  • Pester 4.1.1.
  • Windows server 2012 R1
  • AD Module 1.0.0.0.

enter image description here

DarkLite1
  • 13,637
  • 40
  • 117
  • 214
  • Your code works for me, what version of Pester are you using? I just ran it with the latest version. Your test2 fails because it returns 12 results not 2, but that is correct as it returns two users for two groups for the 3 users found by the first get-aduser call. – Mark Wragg Jan 16 '18 at 13:23

1 Answers1

1

It seems like the error you're seeing is occurring because the users you create in your Mock of Get-ADGroupMember aren't being mapped to/accepted by the Identity parameter because it accepts pipeline input ByValue and expects an ADUser type object.

You can work around that by using New-MockObject to create the specific object type you need. Here's an alternative option for your Mock of Get-ADGroupMember:

Mock Get-ADGroupMember {
    1..2 | ForEach-Object {
        $User = New-MockObject -Type Microsoft.ActiveDirectory.Management.ADUser
        $User.SamAccountName = "Member$_"
        $User
    }
}

I've used a ForEach as a quick way to return the 2 users you were returning before, with the value you were setting but as actual ADUser objects.

This doesn't actually make your -ParameterFilter on the second Get-ADUser work however. That seems to be again because the User is an object but you're comparing it to a string, it doesn't evaluate as true.

One possible workaround for this (that I think works somewhat for your specific use case) is not to check for a specific value of $Identity but just to check if it has any value:

Mock Get-ADUser {
    [PSCustomObject]@{SamAccountName = 'User4'}
    [PSCustomObject]@{SamAccountName = 'User5'}
} -ParameterFilter { $identity }

This causes your 2nd Mock to always be called for the 2nd Get-ADUser in your script as that's the only one that gets piped an Identity value. This isn't exactly what you were trying to achieve, but I figure might help a little.

Mark Wragg
  • 22,105
  • 7
  • 39
  • 68
  • Thank you Mark, really appreciate your help. When I replace my code with your examples I still have the same errors. Would it be possible to post a full script that works on your end? Maybe we can avoid piping to `Get-ADUser` so the `Mock` with `-ParameterFiler` does work for a single `SamAccountName` that matches? – DarkLite1 Jan 17 '18 at 07:29
  • Other than the above suggested changes, my code is exactly the same as yours, but what is still curious is that I don't get your errors about `-Identity` even before changing the `Mock`. The only difference is I am running it on a Win 7 machine with the AD PowerShell cmdlets installed. Have you tried running it elsewhere at all? – Mark Wragg Jan 17 '18 at 08:57
  • 1
    Just tried your suggestion and ran the code on another server with another OS (Win 2008) and another PowerShell version (4.0). Still the same errors I'm afraid... I will +1 your answer for the help anyhow. Thx Mark – DarkLite1 Jan 17 '18 at 09:13