Tests/Unit/MSFT_ADOptionalFeature.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_ADOptionalFeature' #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 $forestName = 'contoso.com' $testCredential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( 'DummyUser', (ConvertTo-SecureString -String 'DummyPassword' -AsPlainText -Force) ) $featureParameters = @{ FeatureName = 'Recycle Bin Feature' ForestFqdn = $forestName EnterpriseAdministratorCredential = $testCredential } $testFeatureProperties = $featureParameters.Clone() $testFeatureProperties.FeatureName = "Test Feature" $badCredentialsProperties = $featureParameters.Clone() $badCredentialsProperties.EnterpriseAdministratorCredential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( 'Invalid', (ConvertTo-SecureString -String 'Invalid' -AsPlainText -Force) ) $mockADForestDesiredState = @{ Name = $forestName ForestMode = [Microsoft.ActiveDirectory.Management.ADForestMode]7 # Windows2016Forest RootDomain = $forestName DomainNamingMaster = "DC01" } $mockADForestNonDesiredState = $mockADForestDesiredState.Clone() $mockADForestNonDesiredState.ForestMode = [Microsoft.ActiveDirectory.Management.ADForestMode]0 # Windows2000Forest $mockADDomainDesiredState = @{ Name = $forestName DomainMode = [Microsoft.ActiveDirectory.Management.ADDomainMode]7 # Windows2016Domain } $mockADDomainNonDesiredState = $mockADDomainDesiredState.Clone() $mockADDomainNonDesiredState.DomainMode = [Microsoft.ActiveDirectory.Management.ADDomainMode]0 # Windows2000Domain $mockADRecycleBinDisabled = @{ EnabledScopes = @() Name = "Recycle Bin Feature" RequiredDomainMode = $null RequiredForestMode = [Microsoft.ActiveDirectory.Management.ADForestMode]4 # Windows2008R2 } $mockADRecycleBinEnabled= $mockADRecycleBinDisabled.Clone() $mockADRecycleBinEnabled.EnabledScopes = @( "CN=Partitions,CN=Configuration,DC=contoso,DC=com", "CN=NTDS Settings,CN=DC01,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=contoso,DC=com" ) $mockTestFeatureDisabled = @{ EnabledScopes = @() Name = "Test Feature" RequiredDomainMode = [Microsoft.ActiveDirectory.Management.ADDomainMode]7 # Windows2016Domain RequiredForestMode = [Microsoft.ActiveDirectory.Management.ADForestMode]7 # Windows2016Forest } Describe 'MSFT_ADOptionalFeature\Get-TargetResource' { Mock -CommandName Get-ADForest -MockWith { $mockADForestDesiredState } Context 'When feature is enabled' { Mock -CommandName Get-ADOptionalFeature -MockWith { $mockADRecycleBinEnabled } It 'Should return expected properties' { $targetResource = Get-TargetResource @featureParameters $targetResource.FeatureName | Should -Be $featureParameters.FeatureName $targetResource.ForestFqdn | Should -Be $featureParameters.ForestFqdn $targetResource.Enabled | Should -BeTrue $targetResource.EnterpriseAdministratorCredential.Username | Should -Be $featureParameters.EnterpriseAdministratorCredential.Username $targetResource.EnterpriseAdministratorCredential.Password | Should -BeNullOrEmpty Assert-MockCalled -CommandName Get-ADOptionalFeature -Times 1 -Exactly -Scope It -ParameterFilter { $Identity.ToString() -eq $featureParameters.FeatureName -and $Server -eq $mockADForestDesiredState.DomainNamingMaster -and $Credential.Username -eq $featureParameters.EnterpriseAdministratorCredential.Username } Assert-MockCalled -CommandName Get-ADForest -Times 1 -Exactly -Scope It -ParameterFilter { $Server -eq $featureParameters.ForestFQDN -and $Credential.Username -eq $featureParameters.EnterpriseAdministratorCredential.Username } } } Context 'When feature isnt enabled' { Mock -CommandName Get-ADOptionalFeature -MockWith { $mockADRecycleBinDisabled } It 'Should return expected properties' { $targetResource = Get-TargetResource @featureParameters $targetResource.FeatureName | Should -Be $featureParameters.FeatureName $targetResource.ForestFqdn | Should -Be $featureParameters.ForestFqdn $targetResource.Enabled | Should -BeFalse $targetResource.EnterpriseAdministratorCredential.Username | Should -Be $featureParameters.EnterpriseAdministratorCredential.Username $targetResource.EnterpriseAdministratorCredential.Password | Should -BeNullOrEmpty } } context 'When domain is not available' { It 'Should throw "Credential Error" when domain is available but authentication fails' { Mock -CommandName Get-ADOptionalFeature -ParameterFilter { $Credential.Username -eq $badCredentialsProperties.EnterpriseAdministratorCredential.Username } -MockWith { throw New-Object System.Security.Authentication.AuthenticationException } { Get-TargetResource @badCredentialsProperties } | Should -Throw $script:localizedData.CredentialError } It 'Should throw "Cannot contact forest" when forest cannot be located' { Mock -CommandName Get-ADOptionalFeature -MockWith { throw New-Object Microsoft.ActiveDirectory.Management.ADServerDownException } { Get-TargetResource @featureParameters } | Should -Throw ($script:localizedData.ForestNotFound -f $featureParameters.ForestFQDN) } } context 'When unknown error occurs' { It 'Should throw "unknown" when unknown error occurs' { Mock -CommandName Get-ADOptionalFeature -MockWith { throw "Unknown error" } { Get-TargetResource @featureParameters } | Should -Throw } } } Describe 'MSFT_ADOptionalFeature\Test-TargetResource' { Mock -CommandName Get-ADForest -MockWith { $mockADForestDesiredState } Context 'When target resource in desired state' { Mock -CommandName Get-ADOptionalFeature -MockWith { $mockADRecycleBinEnabled } It 'Should return $true' { Test-TargetResource @featureParameters | Should -BeTrue } } Context 'When target not in desired state' { Mock -CommandName Get-ADOptionalFeature -MockWith { $mockADRecycleBinDisabled } It 'Should return $false' { Test-TargetResource @featureParameters | Should -BeFalse } } } Describe 'MSFT_ADOptionalFeature\Set-TargetResource' { Mock -CommandName Get-ADForest -MockWith { $mockADForestDesiredState } Mock -CommandName Get-ADDomain -MockWith { $mockADDomainDesiredState } Mock -CommandName Get-ADOptionalFeature -MockWith { $mockADRecycleBinDisabled } Context 'When domain and forest requirements are met' { Mock -CommandName Enable-ADOptionalFeature It 'Should call Enable-ADOptionalFeature with correct properties' { Set-TargetResource @featureParameters Assert-MockCalled Enable-ADOptionalFeature -Scope It -Times 1 -Exactly -ParameterFilter { $Identity.ToString() -eq $featureParameters.FeatureName -and $Scope.ToString() -eq "ForestOrConfigurationSet" -and $Server -eq $mockADForestDesiredState.DomainNamingMaster } Assert-MockCalled -CommandName Get-ADOptionalFeature -Times 1 -Exactly -Scope It -ParameterFilter { $Identity.ToString() -eq $featureParameters.FeatureName -and $Server -eq $mockADForestDesiredState.DomainNamingMaster -and $Credential.Username -eq $featureParameters.EnterpriseAdministratorCredential.Username } Assert-MockCalled -CommandName Get-ADForest -Times 1 -Exactly -Scope It -ParameterFilter { $Server -eq $featureParameters.ForestFQDN -and $Credential.Username -eq $featureParameters.EnterpriseAdministratorCredential.Username } Assert-MockCalled -CommandName Get-ADDomain -Times 1 -Exactly -Scope It -ParameterFilter { $Server -eq $featureParameters.ForestFQDN -and $Credential.Username -eq $featureParameters.EnterpriseAdministratorCredential.Username } } } Context 'When forest requirements are not met' { Mock -CommandName Get-ADForest -MockWith { $mockADForestNonDesiredState } Mock -CommandName Enable-ADOptionalFeature It 'Should throw exception that forest functional level is too low' { { Set-TargetResource @featureParameters } | Should -Throw Assert-MockCalled Enable-ADOptionalFeature -Scope It -Times 0 -Exactly } } Context 'When domain requirements are not met' { Mock -CommandName Get-ADOptionalFeature -MockWith { $mockTestFeatureDisabled } Mock -CommandName Get-ADForest -MockWith { $mockADForestDesiredState } Mock -CommandName Get-ADDomain -MockWith { $mockADDomainNonDesiredState } Mock -CommandName Enable-ADOptionalFeature It 'Should throw exception that domain functional level is too low' { { Set-TargetResource @testFeatureProperties } | Should -Throw Assert-MockCalled Enable-ADOptionalFeature -Scope It -Times 0 -Exactly } } context 'When domain is not available' { It 'Should throw "Credential Error" when forest is available but authentication fails' { Mock -CommandName Get-ADForest -ParameterFilter { $Credential.Username -eq $badCredentialsProperties.EnterpriseAdministratorCredential.Username } -MockWith { throw New-Object System.Security.Authentication.AuthenticationException } { Set-TargetResource @badCredentialsProperties } | Should -Throw $script:localizedData.CredentialError } It 'Should throw "Cannot contact forest" when forest cannot be located' { Mock -CommandName Get-ADForest -MockWith { throw New-Object Microsoft.ActiveDirectory.Management.ADServerDownException } { Set-TargetResource @featureParameters } | Should -Throw ($script:localizedData.ForestNotFound -f $featureParameters.ForestFQDN) } It 'Should throw "Credential Error" when domain is available but authentication fails' { Mock -CommandName Get-ADDomain -ParameterFilter { $Credential.Username -eq $badCredentialsProperties.EnterpriseAdministratorCredential.Username } -MockWith { throw New-Object System.Security.Authentication.AuthenticationException } { Set-TargetResource @badCredentialsProperties } | Should -Throw $script:localizedData.CredentialError } It 'Should throw "Cannot contact forest" when domain cannot be located' { Mock -CommandName Get-ADDomain -MockWith { throw New-Object Microsoft.ActiveDirectory.Management.ADServerDownException } { Set-TargetResource @featureParameters } | Should -Throw ($script:localizedData.ForestNotFound -f $featureParameters.ForestFQDN) } } context 'When unknown error occurs' { It 'Should throw "unknown" when unknown error occurs' { Mock -CommandName Get-ADOptionalFeature -MockWith { throw "Unknown error" } { Get-TargetResource @featureParameters } | Should -Throw } } } } } finally { Invoke-TestCleanup } |