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 } |