Tests/Unit/MSFT_ADUser.Tests.ps1

Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\TestHelpers\ActiveDirectoryDsc.TestHelper.psm1')

if (-not (Test-RunForCITestCategory -Type 'Unit' -Category 'Tests'))
{
    return
}

$script:dscModuleName = 'ActiveDirectoryDsc'
$script:dscResourceName = 'MSFT_ADUser'

#region HEADER

# Unit Test Template Version: 1.2.4
$script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or `
    (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) )
{
    & git @('clone', 'https://github.com/PowerShell/DscResource.Tests.git', (Join-Path -Path $script:moduleRoot -ChildPath 'DscResource.Tests'))
}

Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath (Join-Path -Path 'DSCResource.Tests' -ChildPath 'TestHelper.psm1')) -Force

$TestEnvironment = Initialize-TestEnvironment `
    -DSCModuleName $script:dscModuleName `
    -DSCResourceName $script:dscResourceName `
    -ResourceType 'Mof' `
    -TestType Unit

#endregion HEADER

function Invoke-TestSetup
{
}

function Invoke-TestCleanup
{
    Restore-TestEnvironment -TestEnvironment $TestEnvironment
}

# Begin Testing
try
{
    Invoke-TestSetup

    InModuleScope $script:dscResourceName {
        # Load stub cmdlets and classes.
        Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'Stubs\ActiveDirectory_2019.psm1') -Force

        $testPresentParams = @{
            DomainName = 'contoso.com'
            UserName   = 'TestUser'
            Ensure     = 'Present'
            Verbose    = $true
        }

        $testAbsentParams = $testPresentParams.Clone()
        $testAbsentParams['Ensure'] = 'Absent'

        $fakeADUser = @{
            DistinguishedName     = "CN=$($testPresentParams.UserName),CN=Users,DC=contoso,DC=com"
            Enabled               = $true
            GivenName             = ''
            Name                  = $testPresentParams.UserName
            SamAccountName        = $testPresentParams.UserName
            Surname               = ''
            UserPrincipalName     = ''
            ServicePrincipalName  = @('spn/a', 'spn/b')
        }

        $testDomainController = 'TESTDC'
        $testCredential = [System.Management.Automation.PSCredential]::Empty

        $testStringProperties = @(
            'UserPrincipalName', 'DisplayName', 'Path', 'GivenName', 'Initials', 'Surname', 'Description', 'StreetAddress',
            'POBox', 'City', 'State', 'PostalCode', 'Country', 'Department', 'Division', 'Company', 'Office', 'JobTitle',
            'EmailAddress', 'EmployeeID', 'EmployeeNumber', 'HomeDirectory', 'HomeDrive', 'HomePage', 'ProfilePath',
            'LogonScript', 'Notes', 'OfficePhone', 'MobilePhone', 'Fax', 'Pager', 'IPPhone', 'HomePhone', 'CommonName',
            'Manager', 'LogonWorkstations', 'Organization', 'OtherName'
        )
        $testBooleanProperties = @(
            'PasswordNeverExpires', 'CannotChangePassword', 'TrustedForDelegation', 'Enabled','AccountNotDelegated',
            'AllowReversiblePasswordEncryption', 'CompoundIdentitySupported', 'PasswordNotRequired', 'SmartcardLogonRequired'
        )
        $testArrayProperties = @('ServicePrincipalNames', 'ProxyAddresses')

        $mockWrongThumbnailPhotoHash = '9C09BC64AB56D12A1A7E60D284DEB122'

        $mockThumbnailPhotoHash = 'E3253C13DFF396BE98D6144F0DFA6105'
        $mockThumbnailPhotoBase64 = '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'
        $mockThumbnailPhotoByteArray = [System.Byte[]] (
                    255,216,255,224,0,16,74,70,73,70,0,1,1,1,0,96,0,96,0,0,255,225,0,102,69,120,105,102,0,0,77,77,0,42,0,0,0,8,0,6,1,18,0,3,0,0,0,1,0,1,0,0,3,1,0,5,0,0,0,1,0,0,0,86,3,3,0,1,0,0,0,1,0,0,0,0,81,16,
                    0,1,0,0,0,1,1,0,0,0,81,17,0,4,0,0,0,1,0,0,14,196,81,18,0,4,0,0,0,1,0,0,14,196,0,0,0,0,0,1,134,160,0,0,177,143,255,219,0,67,0,2,1,1,2,1,1,2,2,2,2,2,2,2,2,3,5,3,3,3,3,3,6,4,4,3,5,7,6,7,7,7,6,7,
                    7,8,9,11,9,8,8,10,8,7,7,10,13,10,10,11,12,12,12,12,7,9,14,15,13,12,14,11,12,12,12,255,219,0,67,1,2,2,2,3,3,3,6,3,3,6,12,8,7,8,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
                    12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,255,192,0,17,8,0,96,0,96,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,
                    7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,
                    26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,131,132,133,134,135,136,137,138,146,147,
                    148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,
                    230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,
                    17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,
                    84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,
                    178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,250,255,218,0,12,
                    3,1,0,2,17,3,17,0,63,0,253,252,162,138,9,192,160,2,130,112,41,190,101,124,229,251,123,127,193,84,190,13,255,0,193,57,252,60,179,124,66,241,39,153,226,11,168,188,219,15,12,105,40,183,122,214,160,
                    164,224,50,195,185,86,40,248,111,222,204,209,199,149,42,24,182,20,233,70,140,234,205,83,164,155,111,162,51,171,86,20,226,231,81,164,151,86,125,26,91,7,138,249,91,246,131,255,0,130,216,254,203,
                    255,0,179,55,137,174,180,95,18,252,91,208,110,53,173,62,83,5,221,142,137,20,218,212,214,146,43,21,104,229,251,34,72,35,145,89,72,100,98,25,79,80,43,240,239,254,10,43,255,0,5,249,248,213,251,120,
                    165,247,135,244,187,167,248,91,240,234,232,52,77,161,104,87,110,47,53,24,136,33,150,246,244,109,121,85,129,32,197,24,142,38,83,181,150,78,167,225,83,36,54,81,34,102,56,85,136,68,31,116,18,120,
                    10,7,175,176,175,186,203,120,34,82,143,62,54,92,190,75,127,155,213,125,199,199,227,248,186,49,151,38,18,60,222,111,111,146,63,171,63,217,215,254,11,71,251,49,254,212,190,34,181,209,188,43,241,
                    107,195,233,173,223,72,34,181,211,245,148,155,70,184,187,144,176,85,142,37,187,72,252,201,24,145,132,66,88,246,28,26,250,141,27,47,223,241,175,226,165,101,130,254,54,80,241,75,24,37,95,163,0,
                    71,4,31,167,165,125,239,255,0,4,232,255,0,131,131,126,51,126,194,241,88,248,119,196,19,75,241,91,225,205,170,172,73,164,235,55,141,253,163,166,68,6,2,217,222,182,230,84,81,128,33,148,73,24,85,
                    10,158,80,230,150,101,193,50,140,121,240,82,230,242,118,191,201,237,249,6,3,139,163,41,114,98,227,203,230,182,249,163,250,98,162,190,121,253,132,127,224,167,255,0,7,255,0,224,162,222,24,146,239,
                    225,207,137,86,77,106,202,33,54,165,225,205,73,5,174,179,165,174,64,45,36,25,59,163,203,40,243,98,103,139,36,13,249,200,175,161,55,215,195,86,163,58,83,112,170,154,107,163,62,194,157,72,84,138,
                    157,55,116,250,161,212,82,41,200,165,172,205,3,56,174,79,227,103,198,239,9,126,206,159,12,53,159,26,120,227,196,26,111,133,252,43,160,194,38,191,212,175,165,242,225,133,73,10,170,59,179,187,178,
                    162,34,130,206,236,170,161,153,128,61,83,215,243,155,255,0,7,45,126,222,154,199,237,17,251,106,93,252,41,176,190,154,47,2,124,34,145,109,190,201,28,140,34,212,53,135,136,52,247,82,47,1,154,37,
                    144,65,30,65,41,137,200,63,189,97,94,182,75,149,75,31,137,84,19,178,221,190,203,252,207,55,54,204,163,130,195,186,205,93,236,151,118,122,55,252,20,103,254,14,136,241,119,197,117,189,240,175,236,
                    247,97,121,224,63,15,201,186,25,124,87,169,194,143,173,222,161,24,63,103,129,131,71,104,167,230,195,190,249,72,42,64,129,197,126,81,120,151,196,151,222,41,215,245,29,107,89,212,47,53,77,79,82,
                    157,238,239,181,11,233,218,123,139,185,91,150,146,89,92,150,118,61,217,137,53,235,191,177,15,236,9,241,67,254,10,21,241,78,111,10,252,50,208,99,212,38,211,227,142,125,91,83,188,152,91,105,186,36,
                    50,49,85,146,226,82,9,249,138,182,216,209,94,71,216,229,80,132,114,191,176,31,2,255,0,224,148,255,0,179,63,252,18,10,207,73,241,23,197,187,143,248,92,159,23,46,33,23,154,117,132,250,122,201,103,
                    3,169,193,123,75,39,38,53,216,248,197,197,203,51,6,64,99,17,183,203,95,165,66,120,28,173,172,46,18,14,85,95,217,74,242,126,175,162,252,60,143,207,107,75,21,141,131,197,227,106,40,81,143,218,110,
                    209,94,139,171,63,61,127,224,157,191,240,65,127,141,31,183,168,179,215,175,172,219,225,143,195,153,177,47,252,36,58,245,163,172,247,209,28,29,214,86,103,107,206,8,57,18,57,142,34,57,87,110,135,
                    244,235,225,12,127,178,239,252,17,227,77,109,39,225,23,134,87,226,71,196,133,140,219,234,158,39,184,187,73,174,100,97,195,163,222,237,41,16,39,131,5,172,97,1,83,188,6,201,62,61,251,68,127,193,86,
                    60,65,251,99,120,151,82,240,189,151,137,116,173,23,77,181,145,162,159,195,90,46,161,186,103,11,157,203,115,32,33,231,199,33,148,5,143,140,20,200,38,190,22,253,187,127,104,125,87,225,71,246,31,
                    135,188,55,168,73,165,234,151,136,111,238,230,137,23,204,138,0,74,68,139,184,16,55,48,114,112,51,136,199,98,115,223,28,142,190,46,62,219,54,157,163,255,0,62,224,244,255,0,183,165,215,209,105,230,
                    124,205,110,42,140,43,125,75,35,167,105,61,234,77,107,110,241,139,90,46,205,253,199,233,135,199,15,248,101,255,0,248,43,162,253,143,227,23,133,91,225,95,196,70,143,201,211,124,99,167,93,162,200,
                    188,5,68,123,179,26,164,138,56,2,59,168,202,1,247,89,91,167,230,127,252,20,63,254,8,109,241,151,246,5,91,157,125,109,23,226,71,195,80,12,209,120,167,195,214,207,32,181,135,157,173,123,108,55,61,
                    183,203,130,92,52,144,224,143,222,228,237,20,255,0,97,95,218,71,90,248,145,175,234,222,27,241,54,165,54,169,122,240,125,183,79,154,96,162,70,84,226,104,190,80,55,112,85,198,122,5,126,221,62,226,
                    248,27,255,0,5,66,215,191,97,237,94,199,71,159,197,154,60,154,45,219,170,47,135,53,235,223,221,225,187,193,147,190,219,57,206,64,242,201,36,149,36,230,174,89,45,108,44,61,174,85,63,119,173,57,189,
                    63,237,217,110,190,122,25,210,226,135,42,223,82,206,233,243,79,165,72,45,109,221,197,45,87,123,89,174,204,252,107,240,135,138,245,63,3,248,159,76,215,244,13,83,80,209,181,173,38,101,186,211,245,45,
                    58,233,237,238,172,228,29,36,138,88,200,100,108,28,101,72,224,158,213,250,205,255,0,4,235,255,0,131,163,252,73,240,235,236,62,23,253,162,52,219,143,23,232,169,182,20,241,134,145,108,139,171,90,175,
                    64,110,173,80,42,92,168,227,47,22,201,0,7,228,149,141,122,199,198,175,248,37,119,236,227,255,0,5,115,93,91,90,248,68,223,240,163,126,51,219,91,181,238,165,163,71,97,255,0,18,155,214,200,93,243,91,
                    71,136,192,105,56,51,219,20,124,187,52,177,72,196,10,252,141,253,179,63,97,223,137,95,176,39,197,163,224,223,137,154,7,246,70,161,52,77,115,167,221,219,204,46,44,53,123,112,219,124,235,121,134,55,
                    46,122,171,5,145,50,55,34,229,115,231,212,250,142,102,222,23,23,14,74,171,163,210,75,209,245,95,122,242,62,163,15,91,21,130,130,197,224,170,42,148,101,179,90,197,250,174,143,191,83,250,211,248,63,
                    241,143,194,255,0,30,254,27,105,30,47,240,94,189,166,120,155,195,26,236,62,125,134,165,167,206,38,183,184,92,149,56,97,209,149,131,43,41,195,43,43,43,0,65,3,167,7,34,191,158,47,248,54,47,246,243,
                    213,190,8,126,216,11,240,103,84,190,158,111,4,252,84,89,154,202,214,71,45,30,155,172,197,17,149,38,65,209,68,208,197,36,110,0,249,153,96,39,27,14,127,161,180,175,204,115,140,174,88,12,75,160,221,
                    214,233,247,95,230,126,137,149,102,49,198,225,213,101,163,217,174,204,63,198,191,144,191,248,40,84,237,113,255,0,5,9,253,160,90,70,103,111,248,90,30,40,92,159,69,214,46,212,15,192,0,63,10,254,189,
                    51,215,235,95,200,63,252,20,39,143,248,40,31,237,3,255,0,101,71,197,95,250,122,188,175,165,224,79,247,138,159,225,95,153,225,113,143,251,164,63,196,191,38,126,204,255,0,193,172,58,182,133,240,219,
                    254,9,193,241,51,197,90,164,150,218,109,181,191,141,110,231,212,245,9,7,17,193,6,157,100,119,57,28,236,64,92,250,12,177,238,107,237,255,0,219,255,0,225,4,223,182,87,236,13,227,237,15,192,247,186,
                    110,161,173,235,218,4,247,30,24,212,45,228,138,226,51,118,35,45,11,65,55,42,140,248,40,37,66,10,137,9,4,30,107,243,115,254,8,81,119,246,127,248,33,119,237,0,51,247,181,125,120,127,229,30,206,190,
                    80,176,255,0,130,200,120,239,246,24,248,135,125,166,252,51,154,102,185,177,159,23,246,154,171,180,186,37,196,152,5,131,90,171,2,237,206,12,136,209,63,28,49,24,199,91,200,106,99,49,88,140,93,9,242,
                    212,167,61,19,217,233,125,247,79,240,244,60,137,113,2,194,71,15,128,171,75,158,157,72,93,181,188,117,182,207,70,191,30,215,216,252,251,130,64,96,134,72,212,199,180,7,65,141,173,17,28,143,117,35,
                    240,32,138,253,62,253,145,191,224,138,158,7,255,0,130,148,127,193,48,219,226,23,195,159,136,186,150,175,251,67,216,220,202,218,197,134,171,168,3,101,20,232,236,19,78,153,25,76,145,121,144,44,111,
                    29,193,102,5,136,39,228,200,79,205,31,18,120,130,247,197,222,34,212,181,141,74,227,237,154,150,177,119,53,253,236,229,21,60,249,230,118,146,71,218,160,40,220,236,199,10,0,25,192,0,113,94,181,251,
                    4,254,222,158,58,255,0,130,113,254,208,86,95,16,60,15,55,218,23,2,219,91,208,238,38,104,236,124,69,103,156,155,121,176,14,214,25,45,28,161,75,68,252,225,148,186,63,214,102,212,49,117,104,41,97,101,
                    203,56,235,228,251,175,67,199,202,235,225,97,93,199,17,30,104,75,75,245,94,103,149,235,58,62,189,240,171,199,23,218,78,173,101,172,120,99,196,222,31,187,123,91,203,59,133,123,75,237,54,225,9,12,
                    142,56,100,113,252,142,70,65,231,46,246,235,121,184,185,184,145,157,155,116,179,73,35,110,103,61,89,152,158,73,234,73,53,251,173,255,0,5,10,253,136,254,28,127,193,124,127,101,43,15,218,75,246,113,
                    154,213,190,40,233,182,205,109,127,166,75,229,218,221,107,70,4,5,244,155,245,221,182,45,70,17,180,67,43,182,199,70,65,189,160,146,41,83,240,170,123,73,161,121,96,184,142,123,91,136,89,163,150,57,
                    16,164,144,184,36,21,42,195,33,129,4,16,71,4,16,106,114,124,218,56,218,78,234,211,142,146,143,103,254,69,102,185,91,193,213,77,59,194,91,62,232,254,170,127,224,146,191,5,174,255,0,99,207,248,38,79,
                    195,109,55,199,151,22,122,94,183,109,162,29,95,196,23,119,209,165,147,89,249,238,247,9,21,203,182,62,107,104,36,142,220,188,135,56,183,231,29,7,196,255,0,240,117,7,139,60,51,241,111,246,13,248,55,
                    227,47,15,205,99,171,219,73,227,199,181,176,213,34,79,191,110,250,125,255,0,156,177,177,0,249,111,37,180,103,142,27,202,66,50,0,53,240,183,136,255,0,224,177,223,18,255,0,109,159,28,232,250,79,197,
                    45,74,123,152,238,174,96,180,178,180,210,179,107,164,199,59,17,26,59,90,103,5,217,143,250,198,103,101,46,64,218,167,3,232,255,0,248,45,38,239,248,113,175,236,219,255,0,99,191,254,217,235,21,242,244,
                    242,58,152,92,93,28,109,121,222,164,234,106,150,202,233,189,250,254,71,175,12,250,56,149,91,47,163,75,150,148,41,182,155,221,217,165,178,209,119,239,232,124,3,255,0,4,182,186,146,207,254,10,91,240,
                    10,72,100,104,220,248,251,71,77,203,221,90,233,21,135,226,164,143,198,191,173,181,234,126,181,252,143,255,0,193,47,191,229,37,31,0,127,236,160,232,191,250,89,21,127,92,32,98,184,120,235,253,230,159,
                    248,127,83,213,224,223,247,105,250,254,136,111,175,212,87,242,15,255,0,5,9,255,0,148,130,126,208,31,246,84,124,85,255,0,167,171,202,254,190,63,198,191,144,159,248,40,84,76,191,240,80,111,218,5,88,
                    16,223,240,180,60,82,112,125,14,179,120,71,232,69,62,5,255,0,120,169,254,21,249,143,140,127,221,33,254,37,249,51,245,51,254,8,107,25,111,248,33,127,199,236,127,208,95,94,255,0,211,69,149,126,117,
                    254,209,31,178,46,165,226,143,25,234,126,32,208,239,173,238,38,212,165,243,229,178,186,253,211,6,32,2,18,78,84,231,25,195,109,198,113,147,223,244,187,254,13,236,240,157,215,196,175,248,34,223,199,
                    143,15,233,49,155,205,98,251,94,214,237,109,237,147,239,201,60,154,53,159,151,31,213,201,80,63,222,21,242,111,197,221,74,111,8,124,62,215,53,171,123,118,184,184,210,236,229,184,142,45,153,37,212,28,
                    100,122,2,50,65,236,167,222,190,207,135,226,165,91,25,30,170,119,252,15,205,184,179,17,90,132,240,83,167,246,161,109,118,126,247,252,20,126,119,95,159,236,163,42,206,12,47,110,204,178,172,159,41,
                    140,175,4,28,244,193,4,115,95,164,95,240,74,47,248,55,123,198,95,182,100,26,127,143,190,47,73,171,124,57,248,85,34,11,155,91,61,159,103,215,60,73,17,25,86,141,92,127,162,219,55,13,231,58,151,117,251,
                    136,3,44,195,204,63,224,137,63,27,191,101,255,0,217,235,227,143,138,60,113,251,73,67,121,125,170,248,126,214,218,255,0,193,79,113,165,79,171,89,11,212,121,26,103,104,98,71,255,0,75,200,129,161,146,
                    96,35,66,36,109,200,225,26,181,191,224,171,95,240,94,175,136,191,240,81,151,212,188,37,225,95,182,252,61,248,63,35,180,107,164,67,113,255,0,19,29,125,1,32,62,163,52,103,27,25,112,77,172,100,198,14,
                    67,180,216,86,28,121,150,35,31,136,174,240,120,56,242,174,179,123,107,209,31,81,151,97,240,52,40,172,94,42,92,207,164,87,234,125,129,251,117,127,193,122,190,23,126,194,95,10,87,224,95,236,103,163,
                    248,104,255,0,98,196,246,103,196,214,81,164,250,22,140,88,12,189,153,203,127,104,93,22,37,154,119,45,22,252,49,105,201,101,31,139,23,186,164,250,181,253,213,229,245,204,247,151,151,146,189,197,205,
                    196,204,100,154,226,71,98,206,236,122,179,51,18,73,234,73,53,250,115,251,55,126,211,223,240,76,143,11,126,207,126,12,211,252,123,240,87,197,151,94,52,177,209,237,224,215,110,37,176,185,186,107,139,
                    213,64,39,147,205,75,165,86,86,147,115,46,21,64,86,81,133,198,7,143,127,193,80,190,55,126,196,223,21,254,13,248,122,207,246,105,248,107,226,47,10,248,198,45,95,206,191,191,154,222,107,91,99,97,228,
                    200,175,19,44,147,201,230,51,72,98,43,180,2,187,27,230,0,237,110,60,150,81,194,84,246,17,195,206,242,122,205,173,252,219,236,118,103,20,222,38,159,183,149,104,242,165,164,87,228,188,206,15,246,126,
                    253,134,53,173,27,197,186,54,191,226,107,200,116,247,210,111,33,190,143,78,183,253,244,198,72,157,93,86,71,251,170,55,40,200,93,217,28,100,100,227,238,63,248,45,156,62,79,252,16,235,246,109,31,245,
                    59,159,253,34,213,235,198,255,0,103,191,24,220,120,239,224,127,134,245,205,73,100,134,238,242,200,53,203,203,199,154,81,154,51,54,79,81,38,207,48,30,225,199,214,189,227,254,11,209,225,139,207,2,127,
                    193,24,127,102,221,31,86,132,217,106,159,240,151,71,118,109,101,249,102,68,147,78,212,228,27,151,168,32,77,24,96,121,82,216,56,53,244,25,252,35,25,225,20,119,117,47,231,240,179,224,248,75,21,136,175,
                    137,198,123,111,177,78,75,77,147,230,95,157,186,246,63,55,191,224,151,255,0,242,146,143,128,63,246,80,116,95,253,44,138,191,174,26,254,71,255,0,224,151,81,52,223,240,82,175,128,33,21,152,255,0,194,
                    192,209,155,0,118,23,113,147,249,0,79,225,95,215,0,108,215,193,241,215,251,205,63,240,254,167,234,28,27,254,237,63,241,126,131,88,215,243,83,255,0,7,28,126,197,122,167,236,197,255,0,5,6,214,188,105,
                    13,156,159,240,134,252,95,99,174,233,247,106,191,187,142,255,0,106,173,237,171,28,1,230,121,128,78,61,86,224,114,74,182,63,165,138,243,111,218,179,246,80,240,31,237,165,240,103,83,240,15,196,109,6,
                    223,94,240,238,164,86,64,140,76,115,217,78,160,236,184,130,85,249,162,153,50,112,234,65,193,101,57,86,101,63,63,145,102,207,47,196,170,214,188,94,141,121,127,192,61,204,227,44,88,220,59,165,179,221,
                    63,51,249,125,255,0,130,114,127,193,78,254,36,127,193,51,126,37,95,235,94,9,109,55,84,209,117,225,20,122,247,135,245,69,38,207,86,88,201,216,193,215,15,12,200,29,194,72,185,3,121,220,146,0,22,191,92,
                    190,11,254,210,127,178,207,252,22,154,88,227,210,239,100,248,55,241,210,243,46,218,93,227,71,29,198,163,56,93,236,98,229,97,212,23,134,57,140,165,198,212,44,202,128,87,196,255,0,240,81,175,248,54,207,
                    226,167,236,166,47,252,77,240,177,239,126,47,120,14,12,202,208,65,10,175,136,244,168,135,252,245,183,92,45,210,143,239,219,13,228,146,124,133,80,90,191,54,129,249,247,46,85,225,147,183,13,27,169,252,
                    195,43,15,168,34,191,74,141,28,38,61,253,119,47,171,201,81,125,165,191,164,163,213,122,159,158,98,21,108,52,62,165,152,210,85,41,118,127,156,90,213,63,67,245,127,246,135,255,0,130,73,220,126,198,222,
                    49,186,213,117,111,2,233,175,103,115,62,232,117,235,20,146,235,76,220,121,1,67,124,182,174,79,240,50,39,57,10,89,64,53,243,151,237,57,251,8,120,235,227,135,134,230,241,199,195,223,8,248,147,198,183,
                    154,29,213,182,149,173,105,218,14,149,113,169,106,1,39,89,222,11,161,12,10,242,58,43,67,36,110,193,73,93,241,118,201,95,75,253,128,63,224,227,159,137,223,179,157,149,191,132,126,49,91,205,241,171,225,
                    212,139,246,121,228,212,101,18,248,130,210,2,112,225,110,37,37,111,23,105,63,187,185,249,155,129,231,34,241,95,177,31,240,76,79,136,127,179,175,198,157,55,196,254,56,253,159,245,171,89,33,241,34,218,
                    157,111,65,71,48,79,161,75,31,154,85,94,205,199,153,111,147,35,142,51,11,4,6,34,87,150,199,48,226,12,110,11,12,227,138,162,156,213,173,56,252,47,85,123,173,226,237,127,94,135,38,93,194,184,124,70,62,
                    53,240,181,219,167,170,148,100,253,248,232,237,103,179,87,183,235,115,240,55,246,95,253,138,124,125,240,135,95,95,21,124,66,240,31,139,188,15,187,205,180,209,32,241,30,143,115,164,221,92,204,162,54,
                    154,104,225,184,68,144,172,107,36,106,31,110,210,210,144,9,42,118,253,69,240,83,254,9,119,113,251,111,248,182,57,244,191,0,216,106,11,111,48,251,86,185,117,230,89,233,241,182,114,68,210,199,129,59,
                    116,38,48,36,126,121,80,9,39,244,223,254,10,177,227,223,217,215,225,13,199,132,124,105,241,251,197,30,68,126,27,182,188,26,71,133,173,223,205,188,241,12,146,152,88,237,183,143,247,210,42,152,21,115,
                    185,33,5,255,0,120,193,107,241,231,246,246,255,0,131,134,62,38,126,210,58,52,190,10,248,71,102,126,6,252,47,183,83,107,109,107,162,202,32,214,175,109,193,194,137,46,33,218,182,168,84,41,242,109,113,
                    183,115,41,150,85,197,105,151,241,6,47,27,134,138,195,82,92,238,252,210,151,192,181,210,221,100,237,242,50,204,184,90,141,28,194,117,177,53,220,105,171,40,198,47,223,106,202,247,106,202,42,247,243,
                    244,62,222,248,209,251,74,254,203,191,240,70,217,124,173,98,241,126,57,124,117,211,177,229,232,122,115,199,246,125,14,113,243,47,157,247,226,178,219,132,230,79,54,228,2,172,145,133,36,15,201,191,248,
                    40,111,252,20,151,226,71,252,20,183,226,181,159,137,188,125,113,99,107,99,162,36,182,250,22,133,167,33,75,13,22,25,10,153,54,110,37,228,150,77,145,239,149,206,91,203,92,5,85,10,60,6,40,76,147,71,20,
                    106,210,77,115,40,142,52,64,89,230,145,219,1,64,28,179,179,16,0,25,36,144,6,73,175,211,31,248,39,55,252,27,69,241,59,246,157,251,15,137,126,48,77,127,240,151,192,211,129,42,216,24,208,248,151,83,140,
                    227,27,33,112,201,102,167,39,230,157,90,64,87,30,70,24,48,210,113,194,224,31,215,113,245,57,234,127,51,223,210,49,232,189,14,220,45,58,184,136,125,79,45,164,169,210,236,186,249,202,91,183,234,98,255,
                    0,193,180,63,177,86,171,251,66,254,222,86,127,18,46,44,229,143,193,191,8,18,75,249,174,217,15,151,117,170,77,19,69,107,106,167,140,178,172,143,59,99,59,68,113,130,7,154,166,191,163,180,21,231,255,0,
                    179,63,236,187,224,95,216,247,225,6,155,224,95,135,94,31,179,240,223,134,116,188,178,91,66,75,188,242,182,55,205,52,140,75,203,43,96,110,119,37,142,0,206,0,3,208,65,201,175,204,243,204,209,230,24,167,
                    94,214,86,178,94,71,232,249,70,92,176,88,101,71,119,187,126,98,209,142,104,162,188,115,211,26,202,22,190,54,255,0,130,139,127,193,16,126,11,255,0,193,67,225,188,214,53,13,49,188,19,241,22,100,253,215,
                    139,116,56,149,46,38,97,208,93,195,196,119,107,211,37,192,148,1,132,149,1,53,246,81,25,34,144,39,53,182,31,19,87,15,53,86,132,156,100,186,163,42,212,41,214,143,37,84,154,243,63,149,31,248,40,47,252,
                    17,231,227,87,252,19,154,254,123,239,22,104,99,196,62,7,71,196,62,47,208,145,238,52,192,164,128,191,105,4,7,180,126,64,196,160,33,99,132,145,235,230,191,7,120,203,88,248,123,226,107,109,111,195,186,
                    198,169,225,253,106,204,48,131,80,211,47,36,180,186,132,55,12,22,88,202,184,4,117,0,224,247,175,236,239,82,210,160,214,52,249,173,46,161,134,234,214,234,54,134,120,102,65,36,115,35,12,50,178,158,25,
                    72,36,16,120,32,215,194,159,180,31,252,27,115,251,44,252,121,215,38,212,237,124,43,172,124,59,190,185,144,201,41,240,126,163,246,27,102,201,39,11,107,34,75,109,26,243,210,56,148,1,197,125,246,93,198,
                    177,112,246,120,248,252,215,95,85,254,95,113,241,152,238,18,106,126,211,5,43,121,63,209,159,205,111,138,252,91,170,248,239,196,119,90,214,189,170,234,122,230,177,123,183,237,58,134,163,119,37,213,212,
                    251,64,85,223,44,133,153,176,160,1,146,112,0,29,43,234,79,248,39,175,252,17,127,227,103,252,20,82,226,215,82,208,116,127,248,68,188,1,35,2,254,46,215,225,146,27,41,211,36,19,103,30,3,222,55,4,102,60,
                    68,8,33,164,66,49,95,182,159,179,183,252,27,139,251,45,254,207,186,220,58,165,199,132,117,79,136,90,141,171,135,138,79,24,106,31,218,16,41,4,17,155,84,88,237,159,167,241,196,213,247,61,142,159,14,155,
                    107,13,189,188,81,65,111,110,130,56,162,137,2,36,106,6,2,128,56,0,1,128,7,74,156,199,141,34,161,236,240,16,183,155,233,232,191,207,238,12,15,9,55,47,105,141,149,252,151,234,207,145,191,224,157,63,240,
                    69,143,131,63,240,78,104,45,117,109,15,74,147,197,159,16,150,19,29,199,139,181,164,89,47,23,112,195,173,180,99,247,118,145,156,176,196,67,121,83,135,146,76,3,95,95,237,25,164,217,78,175,131,196,98,106,
                    215,155,169,90,78,82,125,89,246,84,104,83,163,5,78,146,73,46,193,142,40,3,20,81,88,155,31,255,217)

        #region Function Get-TargetResource
        Describe 'ADUser\Get-TargetResource' {
            BeforeAll {
                Mock -CommandName Assert-Module
                $getTargetResourceParameters = $testPresentParams.Clone()
                $getTargetResourceParameters.Remove('Ensure')
            }

            It "Returns a 'System.Collections.Hashtable' object type" {
                Mock -CommandName Get-ADUser -MockWith { return [PSCustomObject] $fakeADUser }

                $adUser = Get-TargetResource @getTargetResourceParameters

                $adUser -is [System.Collections.Hashtable] | Should -BeTrue
            }

            It "Returns 'Ensure' is 'Present' when user account exists" {
                Mock -CommandName Get-ADUser -MockWith { return [PSCustomObject] $fakeADUser }

                $adUser = Get-TargetResource @getTargetResourceParameters

                $adUser.Ensure | Should -Be 'Present'
            }

            It "Returns 'Ensure' is 'Absent' when user account does not exist" {
                Mock -CommandName Get-ADUser -MockWith { throw New-Object Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException }

                $adUser = Get-TargetResource @getTargetResourceParameters

                $adUser.Ensure | Should -Be 'Absent'
            }

            It "Should throw the correct exception when Get-ADUser returns an unknown error" {
                Mock -CommandName Get-ADUser -MockWith { throw }

                $expectedError = $script:localizedData.RetrievingADUserError -f $getTargetResourceParameters.UserName, $getTargetResourceParameters.DomainName
                { Get-TargetResource @getTargetResourceParameters } | Should -Throw $expectedError
            }

            It "Calls 'Get-ADUser' with 'Server' parameter when 'DomainController' specified" {
                Mock -CommandName Get-ADUser -ParameterFilter { $Server -eq $testDomainController } -MockWith { return [PSCustomObject] $fakeADUser }

                Get-TargetResource @getTargetResourceParameters -DomainController $testDomainController

                Assert-MockCalled -CommandName Get-ADUser -ParameterFilter { $Server -eq $testDomainController } -Scope It
            }

            It "Calls 'Get-ADUser' with 'Credential' parameter when 'Credential' specified" {
                Mock -CommandName Get-ADUser -ParameterFilter { $Credential -eq $testCredential } -MockWith { return [PSCustomObject] $fakeADUser }

                Get-TargetResource @getTargetResourceParameters -Credential $testCredential

                Assert-MockCalled -CommandName Get-ADUser -ParameterFilter { $Credential -eq $testCredential } -Scope It
            }
            It "Should return the correct value for an Array property" {
                Mock -CommandName Get-ADUser -MockWith { return [PSCustomObject] $fakeADUser }

                $adUser = Get-TargetResource @getTargetResourceParameters
                $adUser.ServicePrincipalNames | Should -Be $fakeADUser.ServicePrincipalName
            }

            It "Should return the correct value of 'ChangePassswordAtLogon' if it is true" {
                $mockADUser = $fakeADUser.Clone()
                $mockADUser['pwdLastSet'] = 0
                Mock -CommandName Get-ADUser -MockWith { return [PSCustomObject] $mockADUser }

                $adUser = Get-TargetResource @getTargetResourceParameters
                $adUser.ChangePasswordAtLogon | Should -BeTrue
            }

            It "Should return the correct value of 'ChangePassswordAtLogon' if it is false" {
                $mockADUser = $fakeADUser.Clone()
                $mockADUser['pwdLastSet'] = 12345678
                Mock -CommandName Get-ADUser -MockWith { return [PSCustomObject] $mockADUser }

                $adUser = Get-TargetResource @getTargetResourceParameters
                $adUser.ChangePasswordAtLogon | Should -BeFalse
            }

            It "Should return the correct value of 'ThumbnailPhoto'." {
                $mockADUser = $fakeADUser.Clone()
                $mockADUser['pwdLastSet'] = 12345678
                # This a mock of a real thumbnail-photo (the DSC logo).
                $mockADUser['ThumbnailPhoto'] = $mockThumbnailPhotoByteArray

                Mock -CommandName Get-ADUser -MockWith {
                    return [PSCustomObject] $mockADUser
                }

                $adUser = Get-TargetResource @getTargetResourceParameters
                $adUser.ThumbnailPhoto | Should -Be $mockThumbnailPhotoBase64
                $adUser.ThumbnailPhotoHash | Should -Be $mockThumbnailPhotoHash
            }
        }
        #endregion

        #region Function Test-TargetResource
        Describe 'ADUser\Test-TargetResource' {
            It "Passes when user account does not exist and 'Ensure' is 'Absent'" {
                Mock -CommandName Get-TargetResource -MockWith { return $testAbsentParams }

                Test-TargetResource @testAbsentParams | Should -BeTrue
            }

            It "Passes when user account exists and 'Ensure' is 'Present'" {
                Mock -CommandName Get-TargetResource -MockWith { return $testPresentParams }

                Test-TargetResource @testPresentParams | Should -BeTrue
            }

            It "Passes when user account password matches, 'Password' is specified and 'PasswordNeverResets' is False" {
                Mock -CommandName Get-TargetResource -MockWith { return $testPresentParams }
                Mock -CommandName Test-Password { return $true }

                Test-TargetResource @testPresentParams -Password $testCredential | Should -BeTrue
            }

            It "Passes when user account password does not match, 'Password' is specified and 'PasswordNeverResets' is True" {
                Mock -CommandName Get-TargetResource -MockWith { return $testPresentParams }
                Mock -CommandName Test-Password { return $false }

                Test-TargetResource @testPresentParams -Password $testCredential -PasswordNeverResets $true | Should -BeTrue
            }

            It "Fails when user account does not exist and 'Ensure' is 'Present'" {
                Mock -CommandName Get-TargetResource -MockWith { return $testAbsentParams }

                Test-TargetResource @testPresentParams | Should -BeFalse
            }

            It "Fails when user account exists, and 'Ensure' is 'Absent'" {
                Mock -CommandName Get-TargetResource -MockWith { return $testPresentParams }

                Test-TargetResource @testAbsentParams | Should -BeFalse
            }

            It "Fails when user account password is incorrect, 'Password' is specified and 'PasswordNeverResets' is False" {
                Mock -CommandName Get-TargetResource -MockWith { return $testPresentParams }
                Mock -CommandName Test-Password { return $false }

                Test-TargetResource @testPresentParams -Password $testCredential | Should -BeFalse
            }

            It "Calls 'Test-Password' with 'Default' PasswordAuthentication by default" {
                Mock -CommandName Get-TargetResource -MockWith { return $testPresentParams }
                Mock -CommandName Test-Password -ParameterFilter { $PasswordAuthentication -eq 'Default' } { return $true }

                Test-TargetResource @testPresentParams -Password $testCredential

                Assert-MockCalled -CommandName Test-Password -ParameterFilter { $PasswordAuthentication -eq 'Default' } -Scope It
            }

            It "Calls 'Test-Password' with 'Negotiate' PasswordAuthentication when specified" {
                Mock -CommandName Get-TargetResource -MockWith { return $testPresentParams }
                Mock -CommandName Test-Password -ParameterFilter { $PasswordAuthentication -eq 'Negotiate' } { return $false }

                Test-TargetResource @testPresentParams -Password $testCredential -PasswordAuthentication 'Negotiate'

                Assert-MockCalled -CommandName Test-Password -ParameterFilter { $PasswordAuthentication -eq 'Negotiate' } -Scope It
            }

            foreach ($testParameter in $testStringProperties)
            {
                It "Passes when user account '$testParameter' matches AD account property" {
                    $testParameterValue = 'Test Parameter String Value'
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    $invalidADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = $testParameterValue
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }

                It "Fails when user account '$testParameter' does not match incorrect AD account property value" {
                    $testParameterValue = 'Test Parameter String Value'
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    $invalidADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $invalidADUser[$testParameter] = $testParameterValue.Substring(0, ([System.Int32] $testParameterValue.Length / 2))
                        return $invalidADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

                It "Fails when user account '$testParameter' does not match empty AD account property value" {
                    $testParameterValue = 'Test Parameter String Value'
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    $invalidADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $invalidADUser[$testParameter] = ''
                        return $invalidADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

                It "Fails when user account '$testParameter' does not match null AD account property value" {
                    $testParameterValue = 'Test Parameter String Value'
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    $invalidADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $invalidADUser[$testParameter] = $null
                        return $invalidADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

                It "Passes when empty user account '$testParameter' matches empty AD account property" {
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = ''
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }

                It "Passes when empty user account '$testParameter' matches null AD account property" {
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = $null
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }

            } #end foreach test string property

            foreach ($testParameter in $testBooleanProperties)
            {
                It "Should Pass when user account '$testParameter' is true and matches AD account property" {
                    $testParameterValue = $true
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = $testParameterValue
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }

                It "Should fail when user account '$testParameter' is true and does not match AD account property value" {
                    $testParameterValue = $true
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $invalidADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $invalidADUser[$testParameter] = -not $testParameterValue
                        return $invalidADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

                It "Should pass when user account '$testParameter' is false matches AD account property" {
                    $testParameterValue = $false
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = $testParameterValue
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }

                It "Should fail when user account '$testParameter' is false and does not match AD account property value" {
                    $testParameterValue = $false
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $invalidADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $invalidADUser[$testParameter] = -not $testParameterValue
                        return $invalidADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

            } #end foreach test boolean property

            It "Should pass when ChangePasswordAtLogon is false and matches the AD Account property" {
                $testParameter = 'ChangePasswordAtLogon'
                $testParameterValue = $false
                $testValidPresentParams = $testPresentParams.Clone()
                $testValidPresentParams[$testParameter] = $testParameterValue
                $validADUser = $testPresentParams.Clone()
                Mock -CommandName Get-TargetResource -MockWith {
                    $validADUser[$testParameter] = $testParameterValue
                    return $validADUser
                }

                Test-TargetResource @testValidPresentParams | Should -BeTrue
            }

            It "Should fail when ChangePasswordAtLogon is false and does not match the AD Account property" {
                $testParameter = 'ChangePasswordAtLogon'
                $testParameterValue = $false
                $testValidPresentParams = $testPresentParams.Clone()
                $testValidPresentParams[$testParameter] = $testParameterValue
                $invalidADUser = $testPresentParams.Clone()
                Mock -CommandName Get-TargetResource -MockWith {
                    $invalidADUser[$testParameter] = -not $testParameterValue
                    return $invalidADUser
                }

                Test-TargetResource @testValidPresentParams | Should -BeFalse
            }

            It "Should pass when ChangePasswordAtLogon is true and matches the AD Account property and the user already exists" {
                $testParameter = 'ChangePasswordAtLogon'
                $testParameterValue = $true
                $testValidPresentParams = $testPresentParams.Clone()
                $testValidPresentParams[$testParameter] = $testParameterValue
                $validADUser = $testPresentParams.Clone()
                $validADUser['Ensure'] = 'Present'
                Mock -CommandName Get-TargetResource -MockWith {
                    $validADUser[$testParameter] = $testParameterValue
                    return $validADUser
                }

                Test-TargetResource @testValidPresentParams | Should -BeTrue
            }

            It "Should pass when ChangePasswordAtLogon is true and does not match the AD Account property and the user already exists" {
                $testParameter = 'ChangePasswordAtLogon'
                $testParameterValue = $true
                $testValidPresentParams = $testPresentParams.Clone()
                $testValidPresentParams[$testParameter] = $testParameterValue
                $invalidADUser = $testPresentParams.Clone()
                $invalidADUser['Ensure'] = 'Present'
                Mock -CommandName Get-TargetResource -MockWith {
                    $invalidADUser[$testParameter] = -not $testParameterValue
                    return $invalidADUser
                }

                Test-TargetResource @testValidPresentParams | Should -BeTrue
            }

            It "Should fail when ChangePasswordAtLogon is true and does not match the AD Account property and the user does not exist" {
                $testParameter = 'ChangePasswordAtLogon'
                $testParameterValue = $true
                $testValidPresentParams = $testPresentParams.Clone()
                $testValidPresentParams[$testParameter] = $testParameterValue
                $invalidADUser = $testPresentParams.Clone()
                $invalidADUser['Ensure'] = 'Absent'
                Mock -CommandName Get-TargetResource -MockWith {
                    $invalidADUser[$testParameter] = -not $testParameterValue
                    return $invalidADUser
                }

                Test-TargetResource @testValidPresentParams | Should -BeFalse
            }

            foreach ($testParameter in $testArrayProperties)
            {
                It "Passes when user account '$testParameter' matches empty AD account property" {
                    $testParameterValue = @()
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = $testParameterValue
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }

                It "Passes when user account '$testParameter' matches single AD account property" {
                    $testParameterValue = @('Entry1')
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = $testParameterValue
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }
                It "Passes when user account '$testParameter' matches multiple AD account property" {
                    $testParameterValue = @('Entry1', 'Entry2')
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = $testParameterValue
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeTrue
                }
                It "Fails when user account '$testParameter' does not match AD account property count" {
                    $testParameterValue = @('Entry1', 'Entry2')
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = @('Entry1')
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

                It "Fails when user account '$testParameter' does not match AD account property name" {
                    $testParameterValue = @('Entry1')
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = @('Entry2')
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

                It "Fails when user account '$testParameter' does not match empty AD account property" {
                    $testParameterValue = @('Entry1')
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = @()
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

                It "Fails when empty user account '$testParameter' does not match AD account property" {
                    $testParameterValue = @()
                    $testValidPresentParams = $testPresentParams.Clone()
                    $testValidPresentParams[$testParameter] = $testParameterValue
                    $validADUser = $testPresentParams.Clone()
                    Mock -CommandName Get-TargetResource -MockWith {
                        $validADUser[$testParameter] = @('ExtraEntry1')
                        return $validADUser
                    }

                    Test-TargetResource @testValidPresentParams | Should -BeFalse
                }

            }#end foreach test array property

            Context 'When the system is in the desired state' {
                Context 'When the parameter ThumbnailPhoto is in desired state' {
                    Context 'When the current thumbnail photo is the correct one' {
                        BeforeAll {
                            $testTargetResourceParameters = $testPresentParams.Clone()
                            $testTargetResourceParameters['ThumbnailPhoto'] = $mockThumbnailPhotoBase64

                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $testTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $mockThumbnailPhotoHash

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should return $true' {
                            Test-TargetResource @testTargetResourceParameters | Should -BeTrue
                        }
                    }

                    Context 'When no thumbnail photo should exist' {
                        BeforeAll {
                            $testTargetResourceParameters = $testPresentParams.Clone()
                            $testTargetResourceParameters['ThumbnailPhoto'] = ''

                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $testTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $null

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should return $true' {
                            Test-TargetResource @testTargetResourceParameters | Should -BeTrue
                        }
                    }
                }
            }

            Context 'When the system is not in the desired state' {
                Context 'When the parameter ThumbnailPhoto does not match' {
                    Context 'When there are no current thumbnail photo' {
                        BeforeAll {
                            $testTargetResourceParameters = $testPresentParams.Clone()
                            $testTargetResourceParameters['ThumbnailPhoto'] = $mockThumbnailPhotoBase64

                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $testTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $null

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should return $false' {
                            Test-TargetResource @testTargetResourceParameters | Should -BeFalse
                        }
                    }

                    Context 'When the current thumbnail photo is not the one that is desired' {
                        BeforeAll {
                            $testTargetResourceParameters = $testPresentParams.Clone()
                            $testTargetResourceParameters['ThumbnailPhoto'] = $mockThumbnailPhotoBase64

                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $testTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $mockWrongThumbnailPhotoHash

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should return $false' {
                            Test-TargetResource @testTargetResourceParameters | Should -BeFalse
                        }
                    }

                    Context 'When there are a current thumbnail photo, but no thumbnail photo should be set' {
                        BeforeAll {
                            $testTargetResourceParameters = $testPresentParams.Clone()
                            $testTargetResourceParameters['ThumbnailPhoto'] = ''

                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $testTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $mockThumbnailPhotoHash

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should return $false' {
                            Test-TargetResource @testTargetResourceParameters | Should -BeFalse
                        }
                    }
                }
            }
        }
        #endregion

        #region Function Set-TargetResource
        Describe 'ADUser\Set-TargetResource' {
            BeforeAll {
                Mock -CommandName Assert-Module
            }

            Context 'When running unit tests that need refactor' {
                It "Calls 'New-ADUser' when 'Ensure' is 'Present' and the account does not exist" {
                    $newUserName = 'NewUser'
                    $newAbsentParams = $testAbsentParams.Clone()
                    $newAbsentParams['UserName'] = $newUserName
                    $newPresentParams = $testPresentParams.Clone()
                    $newPresentParams['UserName'] = $newUserName
                    Mock -CommandName New-ADUser -ParameterFilter { $Name -eq $newUserName }
                    Mock -CommandName Set-ADUser
                    Mock -CommandName Get-TargetResource -ParameterFilter { $Username -eq $newUserName } { return $newAbsentParams }

                    Set-TargetResource @newPresentParams

                    Assert-MockCalled -CommandName New-ADUser -ParameterFilter { $Name -eq $newUserName } -Scope It
                }

                It "Calls 'Move-ADObject' when 'Ensure' is 'Present', the account exists but Path is incorrect" {
                    $testTargetPath = 'CN=Users,DC=contoso,DC=com'
                    Mock -CommandName Set-ADUser
                    Mock -CommandName Get-ADUser -MockWith {
                        $duffADUser = $fakeADUser.Clone()
                        $duffADUser['DistinguishedName'] = "CN=$($testPresentParams.UserName),OU=WrongPath,DC=contoso,DC=com"
                        return $duffADUser
                    }
                    Mock -CommandName Move-ADObject -ParameterFilter { $TargetPath -eq $testTargetPath }

                    Set-TargetResource @testPresentParams -Path $testTargetPath -Enabled $true

                    Assert-MockCalled -CommandName Move-ADObject -ParameterFilter { $TargetPath -eq $testTargetPath } -Scope It
                }

                It "Calls 'Rename-ADObject' when 'Ensure' is 'Present', the account exists but 'CommonName' is incorrect" {
                    $testCommonName = 'Test Common Name'
                    Mock -CommandName Set-ADUser
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Rename-ADObject -ParameterFilter { $NewName -eq $testCommonName }

                    Set-TargetResource @testPresentParams -CommonName $testCommonName -Enabled $true

                    Assert-MockCalled -CommandName Rename-ADObject -ParameterFilter { $NewName -eq $testCommonName } -Scope It
                }

                It "Calls 'Set-ADAccountPassword' when 'Password' parameter is specified and 'PasswordNeverResets' is False" {
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Set-ADUser
                    Mock -CommandName Set-ADAccountPassword -ParameterFilter { $NewPassword -eq $testCredential.Password }
                    Mock -CommandName Test-Password -MockWith { $false }

                    Set-TargetResource @testPresentParams -Password $testCredential

                    Assert-MockCalled -CommandName Set-ADAccountPassword -ParameterFilter { $NewPassword -eq $testCredential.Password } -Scope It
                }

                It "Does not call 'Set-ADAccountPassword' when 'Password' parameter is specified and 'PasswordNeverResets' is True" {
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Set-ADUser
                    Mock -CommandName Set-ADAccountPassword

                    Set-TargetResource @testPresentParams -Password $testCredential -PasswordNeverResets $true

                    Assert-MockCalled -CommandName Set-ADAccountPassword -Scope It -Times 0
                }

                It "Does not call 'Set-ADAccountPassword' when 'Password' parameter is specified and is in the desired state" {
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Set-ADUser
                    Mock -CommandName Set-ADAccountPassword
                    Mock -CommandName Test-Password -MockWith { $true }

                    Set-TargetResource @testPresentParams -Password $testCredential

                    Assert-MockCalled -CommandName Set-ADAccountPassword -Scope It -Times 0
                }

                It "Calls 'Test-Password' with the correct parameters when 'Credential' is specified" {
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Set-ADUser
                    Mock -CommandName Set-ADAccountPassword -ParameterFilter { $NewPassword -eq $testCredential.Password }
                    Mock -CommandName Test-Password -ParameterFilter { $Credential -eq $testCredential } -MockWith { $true }

                    Set-TargetResource @testPresentParams -Password $testCredential -Credential $testCredential

                    Assert-MockCalled -CommandName Test-Password -ParameterFilter { $Credential -eq $testCredential } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Replace' when existing mismatched AD property is null" {
                    $testADPropertyName = 'Description'
                    Mock -CommandName Get-ADUser -MockWith {
                        $duffADUser = $fakeADUser.Clone()
                        $duffADUser[$testADPropertyName] = $null
                        return $duffADUser
                    }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) }

                    Set-TargetResource @testPresentParams -Description 'My custom description'

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Replace' when existing mismatched AD property is empty" {
                    $testADPropertyName = 'Description'
                    Mock -CommandName Get-ADUser -MockWith {
                        $duffADUser = $fakeADUser.Clone()
                        $duffADUser[$testADPropertyName] = ''
                        return $duffADUser
                    }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) }

                    Set-TargetResource @testPresentParams -Description 'My custom description'

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Clear' when new mismatched AD property is empty" {
                    $testADPropertyName = 'Description'
                    Mock -CommandName Get-ADUser -MockWith {
                        $duffADUser = $fakeADUser.Clone()
                        $duffADUser[$testADPropertyName] = 'Incorrect parameter value'
                        return $duffADUser
                    }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Clear -eq $testADPropertyName }

                    Set-TargetResource @testPresentParams -Description ''

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Clear -eq $testADPropertyName } -Scope It -Exactly 1
                }

                It "Calls 'Set-ADUser' with 'Replace' when existing mismatched AD property is null" {
                    $testADPropertyName = 'Title'
                    Mock -CommandName Get-ADUser -MockWith {
                        $duffADUser = $fakeADUser.Clone()
                        $duffADUser[$testADPropertyName] = $null
                        return $duffADUser
                    }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) }

                    Set-TargetResource @testPresentParams -JobTitle 'Gaffer'

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Replace' when new mismatched AD property is not empty" {
                    $testADPropertyName = 'Title'
                    Mock -CommandName Get-ADUser -MockWith {
                        $duffADUser = $fakeADUser.Clone()
                        $duffADUser[$testADPropertyName] = 'Incorrect job title'
                        return $duffADUser
                    }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) }

                    Set-TargetResource @testPresentParams -JobTitle 'Gaffer'

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey($testADPropertyName) } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Replace' when existing mismatched AD array property is empty" {
                    $mockSPNs = @('spn/a', 'spn/b')
                    $mockADUser = $fakeADUser.Clone()
                    $mockADUser['ServicePrincipalName'] = ''

                    Mock -CommandName Get-ADUser -MockWith { return $mockADUser }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey('ServicePrincipalName') }

                    Set-TargetResource @testPresentParams -ServicePrincipalNames $mockSPNs

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey('ServicePrincipalName') } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Replace' when existing mismatched AD array property is not empty" {
                    $testSPNs = @('spn/c', 'spn/d')
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey('ServicePrincipalName') }

                    Set-TargetResource @testPresentParams -ServicePrincipalNames $testSPNs

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey('ServicePrincipalName') } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Clear' when new mismatched AD array property is empty" {
                    $testSPNs = ''
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Clear -eq 'ServicePrincipalName' }

                    Set-TargetResource @testPresentParams -ServicePrincipalNames $testSPNs

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Clear -eq 'ServicePrincipalName' } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with 'Replace' when new mismatched AD array property is not empty" {
                    $testSPNs = @('spn/c', 'spn/d')
                    Mock -CommandName Get-ADUser -MockWith { return $fakeADUser }
                    Mock -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey('ServicePrincipalName') }

                    Set-TargetResource @testPresentParams -ServicePrincipalNames $testSPNs

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $Replace.ContainsKey('ServicePrincipalName') } -Scope It -Exactly 1
                }

                It "Calls 'Remove-ADUser' when 'Ensure' is 'Absent' and user account exists" {
                    Mock -CommandName Get-ADUser -MockWith { return [PSCustomObject] $fakeADUser }
                    Mock -CommandName Remove-ADUser -ParameterFilter { $Identity.ToString() -eq $testAbsentParams.UserName }

                    Set-TargetResource @testAbsentParams

                    Assert-MockCalled -CommandName Remove-ADUser -ParameterFilter { $Identity.ToString() -eq $testAbsentParams.UserName } -Scope It
                }

                It "Should call 'Set-ADUser' with the correct parameter when new AD boolean property is true and old property is false" {
                    $mockBoolParam = 'CannotChangePassword'
                    $mockADUser = $fakeADUser.Clone()
                    $mockADUser[$mockBoolParam] = $false
                    Mock -CommandName Get-ADUser -MockWith { return $mockADUser }
                    Mock -CommandName Set-ADUser -ParameterFilter { $mockBoolParam }

                    $mockSetTargetResourceParams = @{
                        $mockBoolParam = $true
                    }
                    Set-TargetResource @testPresentParams @mockSetTargetResourceParams

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $mockBoolParam } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with the correct parameter when new AD boolean property is false and old property is true" {
                    $mockBoolParam = 'CannotChangePassword'
                    $mockADUser = $fakeADUser.Clone()
                    $mockADUser[$mockBoolParam] = $true
                    Mock -CommandName Get-ADUser -MockWith { return $mockADUser }
                    Mock -CommandName Set-ADUser -ParameterFilter { $mockBoolParam }

                    $mockSetTargetResourceParams = @{
                        $mockBoolParam = $false
                    }
                    Set-TargetResource @testPresentParams @mockSetTargetResourceParams

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $mockBoolParam } -Scope It -Exactly 1
                }

                It "Should call 'Set-ADUser' with the correct parameter when 'ChangePasswordAtLogon' is true and the user does exist" {
                    $mockBoolParam = 'ChangePasswordAtLogon'
                    $newPresentParams = $testPresentParams.Clone()
                    $newAbsentParams = $testAbsentParams.Clone()

                    Mock -CommandName Get-TargetResource -ParameterFilter { $Username -eq $newPresentParams.UserName } `
                        -MockWith { $newPresentParams }
                    Mock -CommandName Set-ADUser

                    Set-TargetResource @newPresentParams

                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $ChangePasswordAtLogon -eq $true } `
                        -Scope It -Exactly 0
                }

                It "Should call 'Set-ADUser' with the correct parameter when 'ChangePasswordAtLogon' is true and the user does not exist" {
                    $mockNewADUser = @{
                        DomainName            = 'contoso.com'
                        UserName              = 'NewUser'
                        ChangePasswordAtLogon = $true
                        Ensure                = 'Present'
                    }
                    $mockBoolParam = 'ChangePasswordAtLogon'
                    $mockPreNewUserParams = $mockNewADUser.Clone()
                    $mockPreNewUserParams['Ensure'] = 'Absent'
                    $mockPreNewUserParams[$mockBoolParam] = $false
                    $mockPostNewUserParams = $mockNewADUser.Clone()
                    $mockPostNewUserParams[$mockBoolParam] = $false

                    Mock -CommandName New-ADUser -MockWith {
                        $script:mockNewADUserWasCalled = $true
                    }
                    Mock -CommandName Get-TargetResource `
                        -MockWith {
                            if (-not $script:mockNewADUserWasCalled)
                            {
                                $mockPreNewUserParams
                            }
                            else
                            {
                                $mockPostNewUserParams
                            }
                        }
                    Mock -CommandName Set-ADUser

                    Set-TargetResource @mockNewADUser

                    Assert-MockCalled -CommandName Get-TargetResource -ParameterFilter { $Username -eq $mockPreNewUserParams.UserName }
                    Assert-MockCalled -CommandName Set-ADUser -ParameterFilter { $ChangePasswordAtLogon -eq $true } `
                        -Scope It -Exactly 1
                }

                Context 'When RestoreFromRecycleBin is used' {
                    BeforeAll {
                        Mock -CommandName Get-TargetResource -MockWith {
                            if ($script:mockCounter -gt 0)
                            {
                                return @{
                                    Ensure = 'Present'
                                }
                            }

                            $script:mockCounter++

                            return @{
                                Ensure = 'Absent'
                            }
                        }

                        Mock -CommandName New-ADUser
                        # Had to overwrite parameter filter from an earlier test
                        Mock -CommandName Set-ADUser -ParameterFilter {
                            return $true
                        }
                    }

                    It 'Should calls Restore-AdCommonObject' {
                        $restoreParam = $testPresentParams.Clone()
                        $restoreParam.RestoreFromRecycleBin = $true

                        $script:mockCounter = 0

                        Mock -CommandName Restore-ADCommonObject -MockWith {
                            return [PSCustomObject] @{
                                ObjectClass = 'user'
                            }
                        }

                        Set-TargetResource @restoreParam

                        Assert-MockCalled -CommandName Restore-ADCommonObject -Scope It
                        Assert-MockCalled -CommandName New-ADUser -Times 0 -Exactly -Scope It
                        Assert-MockCalled -CommandName Set-ADUser -Scope It
                    }

                    It 'Should call New-ADUser if no object was found in the recycle bin' {
                        $restoreParam = $testPresentParams.Clone()
                        $restoreParam.RestoreFromRecycleBin = $true
                        $script:mockCounter = 0

                        Mock -CommandName Restore-ADCommonObject

                        Set-TargetResource @restoreParam

                        Assert-MockCalled -CommandName Restore-ADCommonObject -Scope It
                        Assert-MockCalled -CommandName New-ADUser -Scope It
                        Assert-MockCalled -CommandName Set-ADUser -Scope It
                    }

                    It 'Should throw the correct error when then object cannot be restored from recycle bin' {
                        $restoreParam = $testPresentParams.Clone()
                        $restoreParam.RestoreFromRecycleBin = $true

                        $script:mockCounter = 0

                        Mock -CommandName Restore-ADCommonObject -MockWith { throw (New-Object -TypeName System.InvalidOperationException) }

                        { Set-TargetResource @restoreParam } | Should -Throw

                        Assert-MockCalled -CommandName Restore-ADCommonObject -Scope It
                        Assert-MockCalled -CommandName New-ADUser -Scope It -Exactly -Times 0
                        Assert-MockCalled -CommandName Set-ADUser -Scope It -Exactly -Times 0
                    }
                }
            }

            Context 'When the system is in the desired state' {
                Context 'When the parameter ThumbnailPhoto is in desired state' {
                    Context 'When the current thumbnail photo is the correct one' {
                        BeforeAll {
                            $setTargetResourceParameters = $testPresentParams.Clone()
                            $setTargetResourceParameters['ThumbnailPhoto'] = $mockThumbnailPhotoBase64

                            Mock -CommandName Set-ADUser
                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $setTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $mockThumbnailPhotoHash

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should not throw and call the correct mocks' {
                            { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                            Assert-MockCalled -CommandName Set-ADUser -ParameterFilter {
                                # No properties should be replaced in this test.
                                -not $PSBoundParameters.ContainsKey('Replace')
                            } -Scope It -Exactly -Times 1
                        }
                    }

                    Context 'When no thumbnail photo should exist' {
                        BeforeAll {
                            $setTargetResourceParameters = $testPresentParams.Clone()
                            $setTargetResourceParameters['ThumbnailPhoto'] = ''

                            Mock -CommandName Set-ADUser
                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $setTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $null

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should not throw and call the correct mocks' {
                            { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                            Assert-MockCalled -CommandName Set-ADUser -ParameterFilter {
                                # No properties should be replaced in this test.
                                -not $PSBoundParameters.ContainsKey('Replace')
                            } -Scope It -Exactly -Times 1
                        }
                    }
                }
            }

            Context 'When the system is not in the desired state' {
                Context 'When the parameter ThumbnailPhoto does not match' {
                    Context 'When there are no current thumbnail photo' {
                        BeforeAll {
                            $setTargetResourceParameters = $testPresentParams.Clone()
                            $setTargetResourceParameters['ThumbnailPhoto'] = $mockThumbnailPhotoBase64

                            Mock -CommandName Set-ADUser
                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $setTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $null

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should not throw and call the correct mocks' {
                            { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                            Assert-MockCalled -CommandName Set-ADUser -ParameterFilter {
                                $Replace.ContainsKey('ThumbnailPhoto')
                            }-Scope It -Exactly -Times 1
                        }
                    }

                    Context 'When the current thumbnail photo is not the one that is desired' {
                        BeforeAll {
                            $setTargetResourceParameters = $testPresentParams.Clone()
                            $setTargetResourceParameters['ThumbnailPhoto'] = $mockThumbnailPhotoBase64

                            Mock -CommandName Set-ADUser
                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $setTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $mockWrongThumbnailPhotoHash

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should not throw and call the correct mocks' {
                            { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                            Assert-MockCalled -CommandName Set-ADUser -ParameterFilter {
                                $Replace.ContainsKey('ThumbnailPhoto')
                            }-Scope It -Exactly -Times 1
                        }
                    }

                    Context 'When there are a current thumbnail photo, but no thumbnail photo should be set' {
                        BeforeAll {
                            $setTargetResourceParameters = $testPresentParams.Clone()
                            $setTargetResourceParameters['ThumbnailPhoto'] = ''

                            Mock -CommandName Set-ADUser
                            Mock -CommandName Get-TargetResource -MockWith {
                                $mockGetTargetResourceReturnValue = $setTargetResourceParameters.Clone()
                                $mockGetTargetResourceReturnValue['ThumbnailPhotoHash'] = $mockThumbnailPhotoHash

                                return $mockGetTargetResourceReturnValue
                            }
                        }

                        It 'Should not throw and call the correct mocks' {
                            { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                            Assert-MockCalled -CommandName Set-ADUser -ParameterFilter {
                                # Using this to evaluate so correct case is used.
                                $Clear.Contains('thumbnailPhoto')
                            }-Scope It -Exactly -Times 1
                        }
                    }
                }
            }
        }
        #endregion

        Describe 'ADUser\Assert-Parameters' {
            It 'Should not throw when both parameters PasswordNeverExpires and CannotChangePassword are specified' {
                { Assert-Parameters -PasswordNeverExpires $true -CannotChangePassword $true } | Should -Not -Throw
            }

            It 'Should throws the correct error when the parameter Enabled is set to $false and the parameter Password is also specified' {
                {
                    Assert-Parameters -Password $testCredential -Enabled $false
                } | Should -Throw ($script:localizedData.PasswordParameterConflictError -f 'Enabled', $false, 'Password')
            }

            It 'Should not throw when the parameter TrustedForDelegation is specified' {
                { Assert-Parameters -TrustedForDelegation $true } | Should -Not -Throw
            }

            It 'Should throw the correct error when both parameters PasswordNeverExpires and ChangePasswordAtLogon are specified' {
                {
                    Assert-Parameters -PasswordNeverExpires $true -ChangePasswordAtLogon $true
                } | Should -Throw $script:localizedData.ChangePasswordParameterConflictError
            }
        }

        Describe 'ADUser\Get-MD5HashString' {
            It 'Should return the correct hash' {
                Get-MD5HashString -Bytes $mockThumbnailPhotoByteArray | Should -Be $mockThumbnailPhotoHash
            }
        }

        Describe 'ADUser\Get-ThumbnailByteArray' {
            Context 'When providing as Base64-encoded string' {
                It 'Should return the correct byte array' {
                    Get-ThumbnailByteArray -ThumbnailPhoto $mockThumbnailPhotoBase64 | Should -Be $mockThumbnailPhotoByteArray
                }
            }

            Context 'When providing as file path to a jpeg image' {
                It 'Should return the correct byte array' {
                    $mockThumbnailPhotoPath = Join-Path $PSScriptRoot -ChildPath '..\TestHelpers\DSC_Logo_96.jpg'
                    Get-ThumbnailByteArray -ThumbnailPhoto $mockThumbnailPhotoPath | Should -Be $mockThumbnailPhotoByteArray
                }
            }

            Context 'When providing the wrong file path to a jpeg image' {
                It 'Should throw the correct error' {
                    $mockThumbnailPhotoPath = Join-Path $TestDrive -ChildPath 'WrongFile.jpg'
                    { Get-ThumbnailByteArray -ThumbnailPhoto $mockThumbnailPhotoPath } | Should -Throw $script:localizedData.ThumbnailPhotoNotAFile
                }
            }
        }

        Describe 'ADUser\Compare-ThumbnailPhoto' {
            Context 'When current and desired thumbnail photo are the same' {
                It 'Should return $null' {
                    $compareThumbnailPhotoParameters = @{
                        DesiredThumbnailPhoto = $mockThumbnailPhotoBase64
                        CurrentThumbnailPhotoHash = $mockThumbnailPhotoHash
                    }

                    Compare-ThumbnailPhoto @compareThumbnailPhotoParameters | Should -BeNullOrEmpty
                }
            }

            Context 'When there are no current thumbnail photo, and the desired state is that there should be no thumbnail photo' {
                It 'Should return $null' {
                    $compareThumbnailPhotoParameters = @{
                        DesiredThumbnailPhoto = ''
                        CurrentThumbnailPhotoHash = $null
                    }

                    Compare-ThumbnailPhoto @compareThumbnailPhotoParameters | Should -BeNullOrEmpty
                }
            }

            Context 'When current thumbnail photo is not the desired thumbnail photo' {
                It 'Should return $null' {
                    $compareThumbnailPhotoParameters = @{
                        DesiredThumbnailPhoto = $mockThumbnailPhotoBase64
                        CurrentThumbnailPhotoHash = $mockWrongThumbnailPhotoHash
                    }

                    $compareThumbnailPhotoResult = Compare-ThumbnailPhoto @compareThumbnailPhotoParameters
                    $compareThumbnailPhotoResult | Should -BeOfType [System.Collections.Hashtable]
                    $compareThumbnailPhotoResult.CurrentThumbnailPhotoHash | Should -Be $mockWrongThumbnailPhotoHash
                    $compareThumbnailPhotoResult.DesiredThumbnailPhotoHash | Should -Be $mockThumbnailPhotoHash
                }
            }

            Context 'When there are no current thumbnail photo, but the desired state is that there should be a thumbnail photo' {
                It 'Should return $null' {
                    $compareThumbnailPhotoParameters = @{
                        DesiredThumbnailPhoto = $mockThumbnailPhotoBase64
                        CurrentThumbnailPhotoHash = $null
                    }

                    $compareThumbnailPhotoResult = Compare-ThumbnailPhoto @compareThumbnailPhotoParameters
                    $compareThumbnailPhotoResult | Should -BeOfType [System.Collections.Hashtable]
                    $compareThumbnailPhotoResult.CurrentThumbnailPhotoHash | Should -BeNullOrEmpty
                    $compareThumbnailPhotoResult.DesiredThumbnailPhotoHash | Should -Be $mockThumbnailPhotoHash
                }
            }

            Context 'When there are a current thumbnail photo, but the desired state is that there should be no thumbnail photo' {
                It 'Should return $null' {
                    $compareThumbnailPhotoParameters = @{
                        DesiredThumbnailPhoto = ''
                        CurrentThumbnailPhotoHash = $mockThumbnailPhotoHash
                    }

                    $compareThumbnailPhotoResult = Compare-ThumbnailPhoto @compareThumbnailPhotoParameters
                    $compareThumbnailPhotoResult | Should -BeOfType [System.Collections.Hashtable]
                    $compareThumbnailPhotoResult.CurrentThumbnailPhotoHash | Should -Be $mockThumbnailPhotoHash
                    $compareThumbnailPhotoResult.DesiredThumbnailPhotoHash | Should -BeNullOrEmpty
                }
            }
        }
    }
}
finally
{
    Invoke-TestCleanup
}