Pester Mocking Aduser

This topic contains 1 reply, has 2 voices, and was last updated by  Michael 6 months, 1 week ago.

  • Author
    Posts
  • #68335

    James
    Participant

    So I am trying to start using pester more to validate my scripts and I am having a bit of a hard time understanding how to use mock. Here is a quick function I put together and the tests. I am trying to mimic a function that gets an Aduser and throws an error if user is not found.
    #### Function

    function Set-DomainAduser
    {
        [CmdletBinding()]
        Param
        (
            # Param1 help description
            [Parameter(Mandatory=$true,
                       ValueFromPipelineByPropertyName=$true,
                       Position=0)]
          [string]  $User)
    
        Begin
        {
        }
        Process
        {
            try {
              $user =   Get-ADUser $User
              if ($user) {
                  return $User
              }
            }
            catch {
                throw "$user not found in AD Domain"
            }
        }
        End
        {
        }
    }

    ## Test

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
    . "$here\$sut"
    
    Describe 'Test AdUser' {
    	Context 'Return AdObject' {
    		Mock -CommandName 'Get-aduser' -MockWith {return @{name ='here'} }
    		it 'Should return ADObject' {
    			Set-DomainAduser 'me' | should be @{name ='here'} 
    			}
    		}
    	}
    }
    

    Here is the output

     
    Context Return AdObject
          [-] Should return ADObject 211ms
            Expected: {System.Collections.Hashtable}
            But was:  {System.Collections.Hashtable}
    

    Am I approaching the mock function correctly?

  • #68523

    Michael
    Participant

    Hi James,

    I am also on this journey learning DSC along with Pester. I was trying to learn/understand how to utilize Mocking within my Unit testing. Looking at your cod you have to mock the function and not the cmdlet within it. I also removed your Explicit Parameters within your function because when I ran the test and tried to mock the values out, it still expected the parameters. I believe there is a way to avoid this, but I am unaware at the moment. Anyhow I updated your tests with some Mock data to return. I believe since these are expected to be unit testing, you mock out the expected responses for your function and if that changes in the future so does your tests. When you create Integration testing, then you would actually pass in valid data.

    Not sure if this helps any. Good luck!

    ## Set-DomainAdUser.ps1 script
    #### I removed your Mandatory and Position parameters. #######
    function Set-DomainAduser {
        [CmdletBinding()]
        Param
        (
            [string]
            $User
        )
        Begin {
        }
        Process {
                try {
                        $user = Get-ADUser $User
                        if ($user) {
                            return $User
                        }
                }
                catch {
                    throw "$user not found in AD Domain"
                }
        }
        End {
        }
    }
    
    #Set-DomainAdUser.Tests.ps1
    
    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
    . "$here\$sut"
    
    #### I had to specifiy the exact location of this script/module since it was in one of my $PsModulePath's ########
    Import-Module  -Name "C:\Temp\PesterTests\Set-DomainAdUser.ps1" -verbose
    
    Describe 'Test AdUser' {
        $mockdata =
            @{
                Name = "here"
            }
        Context 'Return AdObject' {
    ######## Mock out the function name and not the cmdlet within the function like you did in your previous thread ######
            Mock -CommandName Set-DomainAduser -MockWith { return $mockdata }
            $result = Set-DomainAduser
            it 'Should return ADObject here' {
                $result.Name | Should Be "here"
            }
        }
    }
    

You must be logged in to reply to this topic.