diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e5c800..d3a5677 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- `DhcpServerDsc` + - Migrate unit tests to Pester 5 + - IPv6 preparation work + - Increased code coverage to >85% fixes [#60](https://github.com/dsccommunity/DhcpServerDsc/issues/60). + +### Added + +- Unit tests for `DhcpServerDsc.OptionValueHelper` +- Unit tests for `DSC_xDhcpServerReservation` + ## [4.0.0] - 2025-01-20 ### Changed diff --git a/RequiredModules.psd1 b/RequiredModules.psd1 index e16f52a..7f54f00 100644 --- a/RequiredModules.psd1 +++ b/RequiredModules.psd1 @@ -9,7 +9,7 @@ InvokeBuild = 'latest' PSScriptAnalyzer = 'latest' - Pester = '4.10.1' + Pester = 'latest' Plaster = 'latest' ModuleBuilder = 'latest' ChangelogManagement = 'latest' diff --git a/Resolve-Dependency.psd1 b/Resolve-Dependency.psd1 index 07945f8..27a91e3 100644 --- a/Resolve-Dependency.psd1 +++ b/Resolve-Dependency.psd1 @@ -1,15 +1,15 @@ @{ - Gallery = 'PSGallery' - AllowPrerelease = $false - WithYAML = $true + Gallery = 'PSGallery' + AllowPrerelease = $false + WithYAML = $true - #UseModuleFast = $true + UseModuleFast = $true #ModuleFastVersion = '0.1.2' #ModuleFastBleedingEdge = $true - UsePSResourceGet = $true + UsePSResourceGet = $true #PSResourceGetVersion = '1.0.1' - UsePowerShellGetCompatibilityModule = $true + UsePowerShellGetCompatibilityModule = $true UsePowerShellGetCompatibilityModuleVersion = '3.0.23-beta23' } diff --git a/build.yaml b/build.yaml index 4140066..f8ac629 100644 --- a/build.yaml +++ b/build.yaml @@ -49,7 +49,7 @@ BuildWorkflow: - package_module_nupkg hqrmtest: - - DscResource_Tests_Stop_On_Fail + - Invoke_HQRM_Tests_Stop_On_Fail test: - Pester_Tests_Stop_On_Fail @@ -69,29 +69,51 @@ BuildWorkflow: #################################################### Pester: - OutputFormat: NUnitXML + Configuration: + Run: + Path: + - tests/Unit + Output: + Verbosity: Detailed + StackTraceVerbosity: Full + CIFormat: Auto + CodeCoverage: + CoveragePercentTarget: 85 + OutputPath: CodeCoverage.xml + OutputEncoding: ascii + UseBreakpoints: false + TestResult: + OutputFormat: NUnitXML + OutputEncoding: ascii ExcludeFromCodeCoverage: - Modules/DscResource.Common - Script: - - tests/Unit - Tag: - CodeCoverageThreshold: 65 - CodeCoverageOutputFile: CodeCoverage.xml - CodeCoverageOutputFileEncoding: ascii CodeCoverage: CodeCoverageMergedOutputFile: CodeCov_Merged.xml CodeCoverageFilePattern: Codecov*.xml DscTest: - ExcludeTag: - - "Common Tests - New Error-Level Script Analyzer Rules" - Tag: - ExcludeSourceFile: - - output - ExcludeModuleFile: - - Modules/DscResource.Common - MainGitBranch: main + Pester: + Configuration: + Filter: + ExcludeTag: + - "Common Tests - New Error-Level Script Analyzer Rules" + Output: + Verbosity: Detailed + CIFormat: Auto + TestResult: + Enabled: true + OutputFormat: NUnitXML + OutputEncoding: ascii + OutputPath: ./output/testResults/NUnitXml_HQRM_Tests.xml + Script: + ExcludeSourceFile: + - output + ExcludeModuleFile: + - Modules/DscResource.Common + # Must exclude built module file because it should not be tested like MOF-based resources + - DhcpServerDsc.psm1 + MainGitBranch: main ModuleBuildTasks: Sampler: @@ -100,6 +122,8 @@ ModuleBuildTasks: - '*.ib.tasks' DscResource.DocGenerator: - 'Task.*' + DscResource.Test: + - 'Task.*' TaskHeader: | param($Path) @@ -115,6 +139,8 @@ TaskHeader: | GitHubConfig: GitHubFilesToAdd: - 'CHANGELOG.md' + ReleaseAssets: + - output/WikiContent.zip GitHubConfigUserName: dscbot GitHubConfigUserEmail: dsccommunity@outlook.com UpdateChangelogOnPrerelease: false diff --git a/source/DSCResources/DSC_DhcpServerBinding/DSC_DhcpServerBinding.psm1 b/source/DSCResources/DSC_DhcpServerBinding/DSC_DhcpServerBinding.psm1 index 04de08c..0bdf7d7 100644 --- a/source/DSCResources/DSC_DhcpServerBinding/DSC_DhcpServerBinding.psm1 +++ b/source/DSCResources/DSC_DhcpServerBinding/DSC_DhcpServerBinding.psm1 @@ -42,7 +42,7 @@ function Get-TargetResource if ($bindings.InterfaceAlias -inotcontains $InterfaceAlias) { - $errorMessage = $script:localizedData.InterfaceAliasIsMissing -f $InterfaceAlias, $env:COMPUTERNAME + $errorMessage = $script:localizedData.InterfaceAliasIsMissing -f $InterfaceAlias, (Get-ComputerName) New-ObjectNotFoundException -Message $errorMessage } @@ -149,5 +149,3 @@ function Test-TargetResource return $false } } - -Export-ModuleMember -Function *-TargetResource diff --git a/source/DSCResources/DSC_DhcpServerExclusionRange/DSC_DhcpServerExclusionRange.psm1 b/source/DSCResources/DSC_DhcpServerExclusionRange/DSC_DhcpServerExclusionRange.psm1 index bcc8801..6e7c314 100644 --- a/source/DSCResources/DSC_DhcpServerExclusionRange/DSC_DhcpServerExclusionRange.psm1 +++ b/source/DSCResources/DSC_DhcpServerExclusionRange/DSC_DhcpServerExclusionRange.psm1 @@ -51,16 +51,16 @@ function Get-TargetResource # Check for DhcpServer module/role Assert-Module -ModuleName 'DHCPServer' - $ScopeId = (Get-ValidIpAddress -IpString $ScopeId -AddressFamily $AddressFamily -ParameterName 'ScopeId').IPAddressToString - $IPStartRange = (Get-ValidIpAddress -IpString $IPStartRange -AddressFamily $AddressFamily -ParameterName 'StartRange').IPAddressToString - $IPEndRange = (Get-ValidIpAddress -IpString $IPEndRange -AddressFamily $AddressFamily -ParameterName 'EndRange').IPAddressToString + $ScopeId = Get-ValidIpAddress -IpString $ScopeId -AddressFamily $AddressFamily -ParameterName 'ScopeId' + $StartRange = Get-ValidIpAddress -IpString $IPStartRange -AddressFamily $AddressFamily -ParameterName 'StartRange' + $EndRange = Get-ValidIpAddress -IpString $IPEndRange -AddressFamily $AddressFamily -ParameterName 'EndRange' # Check to ensure startRange is smaller than endRange - if ($IPEndRange.Address -lt $IPStartRange.Address) + if ($EndRange.Address -lt $StartRange.Address) { $errorMessage = $script:localizedData.InvalidStartAndEndRange - New-InvalidArgumentException -ArgumentName 'StartRange' -Message $errorMessage + New-ArgumentException -ArgumentName 'StartRange' -Message $errorMessage } # Retrieve exclusions for the scope @@ -69,8 +69,8 @@ function Get-TargetResource [System.Array] $dhcpExclusionRange = Get-DhcpServerv4ExclusionRange -ScopeId $ScopeId -ErrorAction 'SilentlyContinue' $testExclusionRange = $dhcpExclusionRange | - Where-Object -FIlterScript { - $_.StartRange -eq $IPStartRange -and $_.EndRange -eq $IPEndRange + Where-Object -FilterScript { + $_.StartRange -eq $StartRange -and $_.EndRange -eq $EndRange } $ipStart = $testExclusionRange.StartRange.IPAddressToString @@ -223,7 +223,7 @@ function Test-TargetResource { $errorMessage = $script:localizedData.InvalidStartAndEndRange - New-InvalidArgumentException -ArgumentName 'StartRange' -Message $errorMessage + New-ArgumentException -ArgumentName 'StartRange' -Message $errorMessage } # Retrieve exclusions for the scope @@ -233,13 +233,13 @@ function Test-TargetResource $testExclusionRange = $dhcpExclusionRange | Where-Object -FilterScript { - $_.StartRange -eq $IPStartRange -and $_.EndRange -eq $IPEndRange + $_.StartRange -eq $validStartRange -and $_.EndRange -eq $validEndRange } $ipStart = $testExclusionRange.StartRange.IPAddressToString $ipEnd = $testExclusionRange.EndRange.IPAddressToString - if ($Ensure -ieq 'Present') + if ($Ensure -eq 'Present') { if ($testExclusionRange) { @@ -251,12 +251,12 @@ function Test-TargetResource else { Write-Verbose -Message ($script:localizedData.ExclusionNotFound -f $IPStartRange, $IPEndRange) - Write-Verbose -Message ($script:localizedData.NotInDesiredState -f $ScopeId, $Ensure, "Absent") + Write-Verbose -Message ($script:localizedData.NotInDesiredState -f $ScopeId, $Ensure, 'Absent') return $false } } - elseif ($Ensure -ieq 'Absent') + elseif ($Ensure -eq 'Absent') { if (-not $testExclusionRange) { @@ -268,11 +268,9 @@ function Test-TargetResource else { Write-Verbose -Message ($script:localizedData.FoundExclusion -f $ScopeId, $ipStart, $ipEnd) - Write-Verbose -Message ($script:localizedData.NotInDesiredState -f $ScopeId, $Ensure, "Present") + Write-Verbose -Message ($script:localizedData.NotInDesiredState -f $ScopeId, $Ensure, 'Present') return $false } } } - -Export-ModuleMember -Function *-TargetResource diff --git a/source/DSCResources/DSC_xDhcpServerAuthorization/DSC_xDhcpServerAuthorization.psm1 b/source/DSCResources/DSC_xDhcpServerAuthorization/DSC_xDhcpServerAuthorization.psm1 index 83ff5ae..4a0dbbd 100644 --- a/source/DSCResources/DSC_xDhcpServerAuthorization/DSC_xDhcpServerAuthorization.psm1 +++ b/source/DSCResources/DSC_xDhcpServerAuthorization/DSC_xDhcpServerAuthorization.psm1 @@ -25,7 +25,7 @@ function Get-TargetResource [Parameter()] [ValidateNotNullOrEmpty()] [System.String] - $DnsName = (Get-Hostname), + $DnsName = (Get-ComputerName), [Parameter()] [ValidateNotNullOrEmpty()] @@ -34,7 +34,7 @@ function Get-TargetResource ) Write-Verbose -Message ( - $script:localizedData.GetServerAuthorizationMessage -f $ScopeId + $script:localizedData.GetServerAuthorizationMessage -f $DnsName ) Assert-Module -ModuleName 'DHCPServer' @@ -84,7 +84,7 @@ function Set-TargetResource [Parameter()] [ValidateNotNullOrEmpty()] [System.String] - $DnsName = (Get-Hostname), + $DnsName = (Get-ComputerName), [Parameter()] [ValidateNotNullOrEmpty()] @@ -93,7 +93,7 @@ function Set-TargetResource ) Write-Verbose -Message ( - $script:localizedData.SetServerAuthorizationMessage -f $ScopeId + $script:localizedData.SetServerAuthorizationMessage -f $DnsName ) Assert-Module -ModuleName 'DHCPServer' @@ -110,9 +110,14 @@ function Set-TargetResource { Write-Verbose ($script:localizedData.UnauthorizingServer -f $DnsName, $IPAddress) - Get-DhcpServerInDC | Where-Object -FilterScript { + $dhcpServers = Get-DhcpServerInDC | Where-Object -FilterScript { ($_.DnsName -eq $DnsName) -and ($_.IPAddress -eq $IPAddress) - } | Remove-DhcpServerInDc + } + + foreach ($dhcpServer in $dhcpServers) + { + Remove-DhcpServerInDc -DnsName $dhcpServer.DnsName -IPAddress $dhcpServer.IPAddress + } } } @@ -135,7 +140,7 @@ function Test-TargetResource [Parameter()] [ValidateNotNullOrEmpty()] [System.String] - $DnsName = (Get-Hostname), + $DnsName = (Get-ComputerName), [Parameter()] [ValidateNotNullOrEmpty()] @@ -144,7 +149,7 @@ function Test-TargetResource ) Write-Verbose -Message ( - $script:localizedData.TestServerAuthorizationMessage -f $ScopeId + $script:localizedData.TestServerAuthorizationMessage -f $DnsName ) $targetResource = Get-TargetResource @PSBoundParameters @@ -198,7 +203,7 @@ function Get-IPv4Address Where-Object -FilterScript { $_.IPEnabled -eq 'True' -and $_.IPAddress -notmatch ':' } | - Select-Object -ExpandProperty 'IPAddress' + Select-Object -ExpandProperty 'IPAddress' } #end process } #end function Get-IPv4Address @@ -224,5 +229,3 @@ function Get-Hostname } } #end process } #end function Get-Hostname - -Export-ModuleMember -Function *-TargetResource diff --git a/source/DSCResources/DSC_xDhcpServerClass/DSC_xDhcpServerClass.psm1 b/source/DSCResources/DSC_xDhcpServerClass/DSC_xDhcpServerClass.psm1 index 6f46b5b..947b938 100644 --- a/source/DSCResources/DSC_xDhcpServerClass/DSC_xDhcpServerClass.psm1 +++ b/source/DSCResources/DSC_xDhcpServerClass/DSC_xDhcpServerClass.psm1 @@ -132,7 +132,7 @@ function Set-TargetResource $scopeIDMessage = $script:localizedData.SettingClassIDMessage -f $Name Write-Verbose -Message $scopeIDMessage - set-DhcpServerv4Class -Name $Name -Type $Type -Data $AsciiData -Description $Description + Set-DhcpServerv4Class -Name $Name -Type $Type -Data $AsciiData -Description $Description } else { diff --git a/source/DSCResources/DSC_xDhcpServerReservation/DSC_xDhcpServerReservation.psm1 b/source/DSCResources/DSC_xDhcpServerReservation/DSC_xDhcpServerReservation.psm1 index 8b6ccb7..b02f76d 100644 --- a/source/DSCResources/DSC_xDhcpServerReservation/DSC_xDhcpServerReservation.psm1 +++ b/source/DSCResources/DSC_xDhcpServerReservation/DSC_xDhcpServerReservation.psm1 @@ -402,5 +402,3 @@ function Update-ResourceProperties } #endregion - -Export-ModuleMember -Function *-TargetResource diff --git a/source/DSCResources/DSC_xDhcpServerScope/DSC_xDhcpServerScope.psm1 b/source/DSCResources/DSC_xDhcpServerScope/DSC_xDhcpServerScope.psm1 index b4e858b..06b12f6 100644 --- a/source/DSCResources/DSC_xDhcpServerScope/DSC_xDhcpServerScope.psm1 +++ b/source/DSCResources/DSC_xDhcpServerScope/DSC_xDhcpServerScope.psm1 @@ -227,6 +227,7 @@ function Set-TargetResource SubnetMask = $SubnetMask AddressFamily = $AddressFamily } + Assert-ScopeParameter @ipAddressesAssertionParameters #endregion Input Validation @@ -712,5 +713,3 @@ function Update-ResourceProperties } } # else !dhcpscope } - -Export-ModuleMember -Function *-TargetResource diff --git a/source/Modules/DhcpServerDsc.Common/DhcpServerDsc.Common.psm1 b/source/Modules/DhcpServerDsc.Common/DhcpServerDsc.Common.psm1 index 4bc5dd7..9df202f 100644 --- a/source/Modules/DhcpServerDsc.Common/DhcpServerDsc.Common.psm1 +++ b/source/Modules/DhcpServerDsc.Common/DhcpServerDsc.Common.psm1 @@ -40,7 +40,7 @@ function Get-ValidIPAddress $IpString, [Parameter(Mandatory = $true)] - [ValidateSet('IPv4')] + [ValidateSet('IPv4', 'IPv6')] [System.String] $AddressFamily, @@ -49,8 +49,6 @@ function Get-ValidIPAddress $ParameterName ) - $ipAddressFamily = '' - if ($AddressFamily -eq 'IPv4') { $ipAddressFamily = 'InterNetwork' @@ -145,21 +143,22 @@ function Assert-ScopeParameter $IPEndRange, [Parameter(Mandatory = $true)] + [ValidateSet('IPv4', 'IPv6')] [System.String] $AddressFamily ) # Convert the Subnet Mask to be a valid IPAddress - $netMask = Get-ValidIpAddress -IpString $SubnetMask -AddressFamily $AddressFamily -ParameterName SubnetMask + $netMask = Get-ValidIPAddress -IpString $SubnetMask -AddressFamily $AddressFamily -ParameterName SubnetMask # Convert the ScopeID to be a valid IPAddress $scope = Get-ValidIPAddress -IpString $ScopeId -AddressFamily $AddressFamily -ParameterName ScopeId # Convert the Start Range to be a valid IPAddress - $startRange = Get-ValidIpAddress -IpString $IPStartRange -AddressFamily $AddressFamily -ParameterName IPStartRange + $startRange = Get-ValidIPAddress -IpString $IPStartRange -AddressFamily $AddressFamily -ParameterName IPStartRange # Convert the End Range to be a valid IPAddress - $endRange = Get-ValidIpAddress -IpString $IPEndRange -AddressFamily $AddressFamily -ParameterName IPEndRange + $endRange = Get-ValidIPAddress -IpString $IPEndRange -AddressFamily $AddressFamily -ParameterName IPEndRange # Check to ensure startRange is smaller than endRange if ($endRange.Address -lt $startRange.Address) @@ -220,7 +219,7 @@ function Write-PropertyMessage } } -# Internal function to translate a string to valid IPAddress format +# Internal function to translate a string to valid TimeSpan format function Get-ValidTimeSpan { [CmdletBinding()] diff --git a/source/Modules/DhcpServerDsc.OptionValueHelper/DhcpServerDsc.OptionValueHelper.psm1 b/source/Modules/DhcpServerDsc.OptionValueHelper/DhcpServerDsc.OptionValueHelper.psm1 index e267796..72da172 100644 --- a/source/Modules/DhcpServerDsc.OptionValueHelper/DhcpServerDsc.OptionValueHelper.psm1 +++ b/source/Modules/DhcpServerDsc.OptionValueHelper/DhcpServerDsc.OptionValueHelper.psm1 @@ -74,7 +74,7 @@ function Get-TargetResourceHelper $ReservedIP, [Parameter(Mandatory = $true)] - [ValidateSet('IPv4')] + [ValidateSet('IPv4', 'IPv6')] [System.String] $AddressFamily ) @@ -100,6 +100,7 @@ function Get-TargetResourceHelper VendorClass = $VendorClass userClass = $UserClass } + $currentConfiguration = Get-DhcpServerv4OptionValue @parameters -ErrorAction 'SilentlyContinue' } @@ -115,6 +116,7 @@ function Get-TargetResourceHelper VendorClass = $VendorClass UserClass = $UserClass } + $currentConfiguration = Get-DhcpServerv4OptionValue @parameters -ErrorAction 'SilentlyContinue' } @@ -133,6 +135,7 @@ function Get-TargetResourceHelper VendorClass = $VendorClass ScopeId = $ScopeId } + $currentConfiguration = Get-DhcpServerv4OptionValue @parameters -ErrorAction 'SilentlyContinue' } else @@ -142,6 +145,7 @@ function Get-TargetResourceHelper OptionId = $OptionId VendorClass = $VendorClass } + $currentConfiguration = Get-DhcpServerv4OptionValue @parameters -ErrorAction 'SilentlyContinue' } } @@ -158,6 +162,7 @@ function Get-TargetResourceHelper VendorClass = $VendorClass UserClass = $UserClass } + $currentConfiguration = Get-DhcpServerv4OptionValue @parameters -ErrorAction 'SilentlyContinue' } } @@ -277,7 +282,7 @@ function Test-TargetResourceHelper $ReservedIP, [Parameter(Mandatory = $true)] - [ValidateSet('IPv4')] + [ValidateSet('IPv4', 'IPv6')] [System.String] $AddressFamily, @@ -299,7 +304,9 @@ function Test-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'Server' @parameters + # Testing for Ensure = Present if ($Ensure -eq 'Present') { @@ -349,7 +356,9 @@ function Test-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'Scope' @parameters + # Testing for Ensure = Present if ($Ensure -eq 'Present') { @@ -400,7 +409,9 @@ function Test-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'Policy' @parameters + # Testing for Ensure = Present if ($Ensure -eq 'Present') { @@ -450,7 +461,9 @@ function Test-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'ReservedIP' @parameters + # Testing for Ensure = Present if ($Ensure -eq 'Present') { @@ -576,7 +589,7 @@ function Set-TargetResourceHelper $ReservedIP, [Parameter(Mandatory = $true)] - [ValidateSet('IPv4')] + [ValidateSet('IPv4', 'IPv6')] [System.String] $AddressFamily, @@ -597,6 +610,7 @@ function Set-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'Server' @parameters # Testing for Ensure = Present @@ -629,6 +643,7 @@ function Set-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'Scope' @parameters # Testing for Ensure = Present @@ -639,7 +654,6 @@ function Set-TargetResourceHelper Write-Verbose $scopeSettingValueMessage Set-DhcpServerv4OptionValue -ScopeId $ScopeId -OptionId $OptionId -Value $Value -VendorClass $VendorClass -UserClass $UserClass -Force } - # Ensure = 'Absent' else { @@ -666,6 +680,7 @@ function Set-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'Policy' @parameters # Testing for Ensure = Present @@ -699,7 +714,9 @@ function Set-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'Policy' @parameters + # Testing for Ensure = Present if ($Ensure -eq 'Present') { @@ -730,6 +747,7 @@ function Set-TargetResourceHelper UserClass = $UserClass AddressFamily = $AddressFamily } + $currentConfiguration = Get-TargetResourceHelper -ApplyTo 'ReservedIP' @parameters # Testing for Ensure = Present diff --git a/source/en-US/DhcpServerDsc.strings.psd1 b/source/en-US/DhcpServerDsc.strings.psd1 new file mode 100644 index 0000000..27928a4 --- /dev/null +++ b/source/en-US/DhcpServerDsc.strings.psd1 @@ -0,0 +1,10 @@ +<# + .SYNOPSIS + The localized resource strings in English (en-US) for the + resource DhcpServerDsc module. This file should only contain + localized strings for private functions, public command, and + classes (that are not a DSC resource). +#> + +ConvertFrom-StringData @' +'@ diff --git a/tests/Integration/DSC_DhcpPolicyOptionValue.Integration.Tests.ps1 b/tests/Integration/DSC_DhcpPolicyOptionValue.Integration.Tests.ps1 new file mode 100644 index 0000000..ccad807 --- /dev/null +++ b/tests/Integration/DSC_DhcpPolicyOptionValue.Integration.Tests.ps1 @@ -0,0 +1,2 @@ +Describe 'DSC_DhcpPolicyOptionValue Integration Tests' { +} diff --git a/tests/Unit/DSC_DhcpPolicyOptionValue.Tests.ps1 b/tests/Unit/DSC_DhcpPolicyOptionValue.Tests.ps1 index d0df5d2..afe2e68 100644 --- a/tests/Unit/DSC_DhcpPolicyOptionValue.Tests.ps1 +++ b/tests/Unit/DSC_DhcpPolicyOptionValue.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_DhcpPolicyOptionValue' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_DhcpPolicyOptionValue' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,199 +34,127 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking -} + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - $policyName = 'Test Policy' - $optionId = 67 - $value = @('test Value') - $scopeId = '10.1.1.0' - $vendorClass = '' - $addressFamily = 'IPv4' - $ensure = 'Present' - - $testParams = @{ - PolicyName = $policyName - OptionId = $optionId - ScopeId = $scopeId - VendorClass = $vendorClass - AddressFamily = $addressFamily - Verbose = $true - } - - $getFakeDhcpPolicyv4OptionValue = { - return @{ - PolicyName = $policyName - OptionId = $optionId - Value = $value - ScopeId = $scopeId - VendorClass = $vendorClass - AddressFamily = $addressFamily - } - } - - $getFakeDhcpPolicyv4OptionValueID168 = { - return @{ - PolicyName = $policyName - OptionId = 168 - Value = $value - ScopeId = $scopeId - VendorClass = $vendorClass - AddressFamily = $addressFamily - } - } - - $getFakeDhcpPolicyv4OptionValueDifferentValue = { - return @{ - PolicyName = $policyName - OptionId = $optionId - Value = @('DifferentValue') - ScopeId = $scopeId - VendorClass = $vendorClass - AddressFamily = $addressFamily - } - } - - Describe 'DSC_DhcpPolicyOptionValue\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpPolicyv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - Assert-MockCalled -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } - - It 'Returns a "System.Collections.Hashtable" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpPolicyv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result | Should -BeOfType [System.Collections.Hashtable] - } - - It 'Returns "Absent" when the option value does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - $result.Ensure | Should -Be 'Absent' - } - - It 'Returns all correct values' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpPolicyv4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') - $result = Get-TargetResource @testParams - - $result.Ensure | Should -Be $ensure - $result.OptionId | Should -Be $optionId - $result.PolicyName | Should -Be $policyName - $result.Value | Should -Be @('DifferentValue') - $result.VendorClass | Should -Be $vendorClass - $result.AddressFamily | Should -Be $addressFamily - } + Restore-TestEnvironment -TestEnvironment $script:testEnvironment - It 'Returns the properties as $null when the option does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force - $result = Get-TargetResource @testParams + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - $result.Ensure | Should -Be 'Absent' - $result.OptionId | Should -Be $null - $result.PolicyName | Should -Be $null - $result.Value | Should -Be $null - $result.VendorClass | Should -Be $null - $result.AddressFamily | Should -Be $null +Describe 'DSC_DhcpPolicyOptionValue\Get-TargetResource' -Tag 'Get' { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq 'Policy' + } -MockWith { + @{ + ApplyTo = 'Policy' + ReservedIP = '192.168.10.100' + UserClass = 'AClass' + OptionId = 67 + Value = @('test Value') + VendorClass = '' + ScopeId = '192.168.10.0' + PolicyName = 'Test Policy' + AddressFamily = 'IPv4' + Ensure = 'Present' } } + } + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Describe 'DSC_DhcpPolicyOptionValue\Test-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' + $testParams = @{ + PolicyName = 'Test Policy' + OptionId = 67 + ScopeId = '192.168.10.0' + VendorClass = '' + AddressFamily = 'IPv4' } - It 'Returns a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpPolicyv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value - - $result | Should -BeOfType [System.Boolean] - } + $result = Get-TargetResource @testParams - It 'Returns $true when the option exists and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpPolicyv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' + $result | Should -BeOfType [System.Collections.Hashtable] + $result.Ensure | Should -Be 'Present' + $result.OptionId | Should -Be 67 + $result.PolicyName | Should -Be 'Test Policy' + $result.Value | Should -Be @('test Value') + $result.VendorClass | Should -Be '' + $result.AddressFamily | Should -Be 'IPv4' - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value + $result.ApplyTo | Should -BeNullOrEmpty + $result.ReservedIP | Should -BeNullOrEmpty + $result.UserClass | Should -BeNullOrEmpty + } - $result | Should -Be $true - } + Should -Invoke -CommandName Get-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - It 'Returns $false when the option does not exist and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' +Describe 'DSC_DhcpPolicyOptionValue\Test-TargetResource' -Tag 'Test' { + BeforeAll { + Mock -CommandName Test-TargetResourceHelper -MockWith { + return $true + } + } - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result | Should -Be $false + $testParams = @{ + PolicyName = 'Test Policy' + OptionId = 67 + Value = @('test Value') + ScopeId = '192.168.10.0' + VendorClass = '' + AddressFamily = 'IPv4' } - It 'Returns $false when the option exists and Ensure = Absent ' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpPolicyv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Absent' -Value $value + $result = Test-TargetResource @testParams - $result | Should -Be $false - } + $result | Should -BeTrue } - Describe 'DSC_DhcpPolicyOptionValue\Set-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - Mock -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - Mock -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and definition does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Should -Invoke -CommandName Test-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - It 'Should call "Remove-DhcpServerv4OptionValue" when "Ensure" = "Absent" and Definition does exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpPolicyv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' +Describe 'DSC_DhcpPolicyOptionValue\Set-TargetResource' -Tag 'Set' { + BeforeAll { + Mock -CommandName Set-TargetResourceHelper + } - Set-TargetResource @testParams -Ensure 'Absent' -Value $value + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It + $testParams = @{ + PolicyName = 'Test Policy' + OptionId = 67 + Value = @('test Value') + ScopeId = '192.168.10.0' + VendorClass = '' + AddressFamily = 'IPv4' } - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and option value is different' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpPolicyv4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Set-TargetResource @testParams } + + Should -Invoke -CommandName Set-TargetResourceHelper -Exactly -Times 1 -Scope It } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DSC_DhcpReservedIPOptionValue.Tests.ps1 b/tests/Unit/DSC_DhcpReservedIPOptionValue.Tests.ps1 index 22df433..a9acd82 100644 --- a/tests/Unit/DSC_DhcpReservedIPOptionValue.Tests.ps1 +++ b/tests/Unit/DSC_DhcpReservedIPOptionValue.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_DhcpReservedIPOptionValue' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_DhcpReservedIPOptionValue' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,198 +34,127 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -function Invoke-TestCleanup -{ +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - $optionId = 67 - $reservedIP = '1.1.1.1' - $value = [array] @('testValue1', 'testValue2') - $vendorClass = '' - $userClass = '' - $addressFamily = 'IPv4' - $ensure = 'Present' - - $testParams = @{ - OptionId = $optionId - ReservedIP = $reservedIP - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - Verbose = $true - } + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force - $getFakeDhcpReservedIPv4OptionValue = { - return @{ - OptionId = $optionId - Value = $value - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } - } + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - $getFakeDhcpReservedIPv4OptionValueID168 = { - return @{ - OptionId = 168 - Value = $value - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily +Describe 'DSC_DhcpReservedIPOptionValue\Get-TargetResource' -Tag 'Get' { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -MockWith { + @{ + ApplyTo = 'ReservedIP' + ReservedIP = '192.168.10.100' + UserClass = '' + OptionId = 67 + Value = @('test Value') + VendorClass = '' + ScopeId = '192.168.10.0' + PolicyName = 'Test Policy' + AddressFamily = 'IPv4' + Ensure = 'Present' } } + } - $getFakeDhcpReservedIPv4OptionValueDifferentValue = { - return @{ - OptionId = $optionId - Value = @('DifferentValue') - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ReservedIP = '192.168.10.100' + OptionId = 67 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + } + + $result = Get-TargetResource @testParams + + $result | Should -BeOfType [System.Collections.Hashtable] + $result.Ensure | Should -Be 'Present' + $result.OptionId | Should -Be 67 + $result.Value | Should -Be @('test Value') + $result.VendorClass | Should -Be '' + $result.UserClass | Should -Be '' + $result.AddressFamily | Should -Be 'IPv4' + $result.ReservedIP | Should -Be '192.168.10.100' + $result.UserClass | Should -BeNullOrEmpty + + $result.ApplyTo | Should -BeNullOrEmpty + $result.ScopeId | Should -BeNullOrEmpty + $result.PolicyName | Should -BeNullOrEmpty } - Describe 'DSC_DhcpReservedIPOptionValue\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpReservedIPv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - Assert-MockCalled -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } - - It 'Returns a "System.Collections.Hashtable" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpReservedIPv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result | Should -BeOfType [System.Collections.Hashtable] - } - - It 'Returns "Absent" when the option value does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result.Ensure | Should -Be 'Absent' - } - - It 'Returns all correct values' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpReservedIPv4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result.Ensure | Should -Be $ensure - $result.OptionId | Should -Be $optionId - $result.Value | Should -Be @('DifferentValue') - $result.VendorClass | Should -Be $vendorClass - $result.UserClass | Should -Be $userClass - $result.AddressFamily | Should -Be $addressFamily - } - - It 'Returns the properties as $null when the option does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams + Should -Invoke -CommandName Get-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - $result.Ensure | Should -Be 'Absent' - $result.OptionId | Should -Be $null - $result.ReservedIP | Should -Be $null - $result.Value | Should -Be $null - $result.VendorClass | Should -Be $null - $result.UserClass | Should -Be $null - $result.AddressFamily | Should -Be $null - } +Describe 'DSC_DhcpReservedIPOptionValue\Test-TargetResource' -Tag 'Test' { + BeforeAll { + Mock -CommandName Test-TargetResourceHelper -MockWith { + return $true } + } + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Describe 'DSC_DhcpReservedIPOptionValue\Test-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - It 'Returns a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpReservedIPv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value - - $result | Should -BeOfType [System.Boolean] - } - - It 'Returns $true when the option exists and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpReservedIPv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value - - $result | Should -Be $true - } - - It 'Returns $false when the option does not exist and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value - - $result | Should -Be $false + $testParams = @{ + ReservedIP = '192.168.10.100' + OptionId = 67 + VendorClass = '' + UserClass = '' + Value = @('test Value') + AddressFamily = 'IPv4' } - It 'Returns $false when the option exists and Ensure = Absent ' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpReservedIPv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' + $result = Test-TargetResource @testParams - $result = Test-TargetResource @testParams -Ensure 'Absent' -Value $value - - $result | Should -Be $false - } + $result | Should -BeTrue } - Describe 'DSC_DhcpReservedIPOptionValue\Set-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - Mock -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - Mock -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and definition does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Should -Invoke -CommandName Test-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - It 'Should call "Remove-DhcpServerv4OptionValue" when "Ensure" = "Absent" and Definition does exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpReservedIPv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' +Describe 'DSC_DhcpReservedIPOptionValue\Set-TargetResource' -Tag 'Set' { + BeforeAll { + Mock -CommandName Set-TargetResourceHelper + } - Set-TargetResource @testParams -Ensure 'Absent' -Value $value + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It + $testParams = @{ + ReservedIP = '192.168.10.100' + OptionId = 67 + VendorClass = '' + UserClass = '' + Value = @('test Value') + AddressFamily = 'IPv4' } - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and option value is different' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpReservedIPv4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Set-TargetResource @testParams } + + Should -Invoke -CommandName Set-TargetResourceHelper -Exactly -Times 1 -Scope It } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DSC_DhcpScopeOptionValue.Tests.ps1 b/tests/Unit/DSC_DhcpScopeOptionValue.Tests.ps1 index e71c1ee..43ca330 100644 --- a/tests/Unit/DSC_DhcpScopeOptionValue.Tests.ps1 +++ b/tests/Unit/DSC_DhcpScopeOptionValue.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_DhcpScopeOptionValue' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_DhcpScopeOptionValue' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,202 +34,129 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking -} + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - $optionId = 67 - $value = @('test Value') - $scopeId = '10.1.1.0' - $vendorClass = '' - $userClass = '' - $addressFamily = 'IPv4' - $ensure = 'Present' - - $testParams = @{ - OptionId = $optionId - ScopeId = $scopeId - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - Verbose = $true - } - - $getFakeDhcpScopev4OptionValue = { - return @{ - OptionId = $optionId - Value = $value - ScopeId = $scopeId - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } - } - - $getFakeDhcpScopev4OptionValueID168 = { - return @{ - OptionId = 168 - Value = $value - ScopeId = $scopeId - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } - } - - $getFakeDhcpScopev4OptionValueDifferentValue = { - return @{ - OptionId = $optionId - Value = @('DifferentValue') - ScopeId = $scopeId - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } - } - - Describe 'DSC_DhcpScopeOptionValue\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpScopev4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - Assert-MockCalled -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } - - It 'Returns a "System.Collections.Hashtable" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpScopev4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result | Should -BeOfType [System.Collections.Hashtable] - } - - It 'Returns "Absent" when the option value does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result.Ensure | Should -Be 'Absent' - } - - It 'Returns all correct values' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpScopev4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') - $result.Ensure | Should -Be $ensure - $result.OptionId | Should -Be $optionId - $result.ScopeId | Should -Be $scopeId - $result.Value | Should -Be @('DifferentValue') - $result.VendorClass | Should -Be $vendorClass - $result.UserClass | Should -Be $userClass - $result.AddressFamily | Should -Be $addressFamily - } + Restore-TestEnvironment -TestEnvironment $script:testEnvironment - It 'Returns the properties as $null when the option does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force - $result = Get-TargetResource @testParams + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - $result.Ensure | Should -Be 'Absent' - $result.OptionId | Should -Be $null - $result.ScopeId | Should -Be $null - $result.Value | Should -Be $null - $result.VendorClass | Should -Be $null - $result.UserClass | Should -Be $null - $result.AddressFamily | Should -Be $null +Describe 'DSC_DhcpScopeOptionValue\Get-TargetResource' -Tag 'Get' { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq 'Scope' + } -MockWith { + @{ + ApplyTo = 'Scope' + ReservedIP = '10.1.1.100' + UserClass = 'AClass' + OptionId = 67 + Value = @('test Value') + VendorClass = '' + ScopeId = '10.1.1.0' + PolicyName = 'Test Policy' + AddressFamily = 'IPv4' + Ensure = 'Present' } } + } + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Describe 'DSC_DhcpScopeOptionValue\Test-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' + $testParams = @{ + ScopeId = '10.1.1.0' + OptionId = 67 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' } - It 'Returns a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpScopev4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value - - $result | Should -BeOfType [System.Boolean] - } + $result = Get-TargetResource @testParams - It 'Returns $true when the option exists and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpScopev4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' + $result | Should -BeOfType [System.Collections.Hashtable] + $result.Ensure | Should -Be 'Present' + $result.OptionId | Should -Be 67 + $result.Value | Should -Be @('test Value') + $result.VendorClass | Should -Be '' + $result.UserClass | Should -Be 'AClass' + $result.AddressFamily | Should -Be 'IPv4' - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value + $result.ApplyTo | Should -BeNullOrEmpty + $result.PolicyName | Should -BeNullOrEmpty + $result.ReservedIP | Should -BeNullOrEmpty + } - $result | Should -Be $true - } + Should -Invoke -CommandName Get-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - It 'Returns $false when the option does not exist and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' +Describe 'DSC_DhcpScopeOptionValue\Test-TargetResource' -Tag 'Test' { + BeforeAll { + Mock -CommandName Test-TargetResourceHelper -MockWith { + return $true + } + } - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result | Should -Be $false + $testParams = @{ + ScopeId = '10.1.1.0' + OptionId = 67 + Value = @('test Value') + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + Ensure = 'Present' } - It 'Returns $false when the option exists and Ensure = Absent ' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpScopev4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Absent' -Value $value + $result = Test-TargetResource @testParams - $result | Should -Be $false - } + $result | Should -BeTrue } - Describe 'DSC_DhcpScopeOptionValue\Set-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - Mock -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - Mock -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and definition does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Should -Invoke -CommandName Test-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - It 'Should call "Remove-DhcpServerv4OptionValue" when "Ensure" = "Absent" and Definition does exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpScopev4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' +Describe 'DSC_DhcpScopeOptionValue\Set-TargetResource' -Tag 'Set' { + BeforeAll { + Mock -CommandName Set-TargetResourceHelper + } - Set-TargetResource @testParams -Ensure 'Absent' -Value $value + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It + $testParams = @{ + ScopeId = '10.1.1.0' + OptionId = 67 + Value = @('test Value') + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + Ensure = 'Present' } - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and option value is different' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpScopev4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Set-TargetResource @testParams } + + Should -Invoke -CommandName Set-TargetResourceHelper -Exactly -Times 1 -Scope It } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DSC_DhcpServerBinding.Tests.ps1 b/tests/Unit/DSC_DhcpServerBinding.Tests.ps1 index 618c19d..4feeb95 100644 --- a/tests/Unit/DSC_DhcpServerBinding.Tests.ps1 +++ b/tests/Unit/DSC_DhcpServerBinding.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_DhcpServerBinding' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_DhcpServerBinding' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,153 +34,201 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -function Invoke-TestCleanup -{ +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} -Invoke-TestSetup + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force -try -{ - InModuleScope $script:dscResourceName { - $interfaceAlias = 'Ethernet' - $ensure = 'Present' - $ipAddress = '10.0.0.1' + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - $testParamsPresent = @{ - InterfaceAlias = $interfaceAlias - Ensure = $ensure +Describe 'DhcpServerBinding\Get-TargetResource' -Tag 'Get' { + Context 'When the resource exists' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4Binding -MockWith { + , @( + @{ + InterfaceAlias = 'Ethernet' + IPAddress = [IPAddress] '10.0.0.1' + BindingState = $true + } + ) + } } - $testParamsAbsent = @{ - InterfaceAlias = $interfaceAlias - Ensure = 'Absent' - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $badAliasParams = @{ - InterfaceAlias = 'fake' - Ensure = $ensure - } + $testParams = @{ + InterfaceAlias = 'Ethernet' + } - $setParamsAbsent = @{ - BindingState = $false - InterfaceAlias = $interfaceAlias - } + $result = Get-TargetResource @testParams - $bindingNotPreset = , @( - [PSCustomObject] @{ - InterfaceAlias = $interfaceAlias - IPAddress = [IPAddress] $ipAddress - BindingState = $false + $result.InterfaceAlias | Should -Be $testParams.InterfaceAlias + $result.Ensure | Should -Be 'Present' } - ) - $bindingPresent = , @( - [PSCustomObject] @{ - InterfaceAlias = $interfaceAlias - IPAddress = [IPAddress] $ipAddress - BindingState = $true - } - ) + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerv4Binding -Exactly -Times 1 -Scope It + } + } - Describe 'DhcpServerBinding\Get-TargetResource' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingPresent } + Context 'When the resource does not exist' { + BeforeAll { Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4Binding -MockWith { + , @( + @{ + InterfaceAlias = 'Ethernet' + IPAddress = [IPAddress] '10.0.0.1' + BindingState = $false + } + ) + } + } - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - $result = Get-TargetResource -InterfaceAlias $interfaceAlias + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Assert-MockCalled -CommandName Assert-Module - } + $testParams = @{ + InterfaceAlias = 'Ethernet' + } + + $result = Get-TargetResource @testParams - It 'Returns a "System.Collections.Hashtable" object type' { - $result = Get-TargetResource -InterfaceAlias $interfaceAlias - $result | Should -BeOfType [System.Collections.Hashtable] + $result.InterfaceAlias | Should -Be $testParams.InterfaceAlias + $result.Ensure | Should -Be 'Absent' } - It 'Returns all correct values when binding is present' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingPresent } + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerv4Binding -Exactly -Times 1 -Scope It + } + } - $result = Get-TargetResource -InterfaceAlias $interfaceAlias - $result.Ensure | Should -Be $ensure - $result.InterfaceAlias | Should -Be $interfaceAlias - } + Context 'When the InterfaceAlias is missing' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4Binding + } - It 'Returns all correct values when binding is NOT present' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingNotPreset } + It 'Should throw the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result = Get-TargetResource -InterfaceAlias $interfaceAlias - $result.Ensure | Should -Be 'Absent' - $result.InterfaceAlias | Should -Be $interfaceAlias - } + $testParams = @{ + InterfaceAlias = 'fake' + } - It 'Should throw if InterfaceAlias not found' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingPresent } + $errorRecord = Get-ObjectNotFoundRecord -Message ( + $script:localizedData.InterfaceAliasIsMissing -f $testParams.InterfaceAlias, (Get-ComputerName) + ) - $expectedErrorMessage = $script:localizedData.InterfaceAliasIsMissing -f 'fake', $env:COMPUTERNAME - { Get-TargetResource -InterfaceAlias 'fake' } | Should -Throw $expectedErrorMessage + { Get-TargetResource @testParams } | Should -Throw -ExpectedMessage $errorRecord } + + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerv4Binding -Exactly -Times 1 -Scope It } + } +} - Describe 'DhcpServerBinding\Test-TargetResource' { +Describe 'DhcpServerBinding\Test-TargetResource' -Tag 'Test' { + Context 'When the resource exists' { + BeforeAll { Mock -CommandName Assert-Module - - It 'Returns a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingPresent } - - $result = Test-TargetResource @testParamsPresent - $result | Should -BeOfType [System.Boolean] + Mock -CommandName Get-TargetResource -MockWith { + return @{ + InterfaceAlias = 'Ethernet' + Ensure = 'Present' + } } + } - It 'Returns $true when the binding exists and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingPresent } + Context 'When the resource should be Present' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result = Test-TargetResource @testParamsPresent - $result | Should -Be $true - } + $testParams = @{ + InterfaceAlias = 'Ethernet' + Ensure = 'Present' + } + + $result = Test-TargetResource @testParams - It 'Returns $false when the binding exists and Ensure = Absent' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingPresent } + $result | Should -BeOfType [System.Boolean] + $result | Should -BeTrue + } - $result = Test-TargetResource @testParamsAbsent - $result | Should -Be $false + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-TargetResource -Exactly -Times 1 -Scope It } + } - It 'Returns $true when the binding does not exist and Ensure = Absent' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingNotPreset } + Context 'When the resource should be Absent' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result = Test-TargetResource @testParamsAbsent - $result | Should -Be $true - } + $testParams = @{ + InterfaceAlias = 'Ethernet' + Ensure = 'Absent' + } + + $result = Test-TargetResource @testParams - It 'Returns $false when the binding does not exist and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4Binding -MockWith { return $bindingNotPreset } + $result | Should -BeFalse + } - $result = Test-TargetResource @testParamsPresent - $result | Should -Be $false + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-TargetResource -Exactly -Times 1 -Scope It } } + } +} - Describe 'DhcpServerBinding\Set-TargetResource' { - Mock -CommandName Assert-Module - Mock -CommandName Set-DhcpServerv4Binding -MockWith { return $bindingNotPreset } +Describe 'DhcpServerBinding\Set-TargetResource' -Tag 'Set' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Set-DhcpServerv4Binding -MockWith { + return @{ + InterfaceAlias = 'Ethernet' + IPAddress = [IPAddress] '10.0.0.1' + BindingState = $false + } + } + } - It 'Should call "Set-DhcpServerv4Binding"' { - Set-TargetResource @testParamsPresent + It 'Should call expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Assert-MockCalled -CommandName Set-DhcpServerv4Binding -Times 1 + $testParams = @{ + InterfaceAlias = 'Ethernet' + Ensure = 'Present' } + + Set-TargetResource @testParams } + + Should -Invoke -CommandName Set-DhcpServerv4Binding -Exactly -Times 1 -Scope It } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DSC_DhcpServerExclusionRange.Tests.ps1 b/tests/Unit/DSC_DhcpServerExclusionRange.Tests.ps1 index 347a046..e9aac2d 100644 --- a/tests/Unit/DSC_DhcpServerExclusionRange.Tests.ps1 +++ b/tests/Unit/DSC_DhcpServerExclusionRange.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_DhcpServerExclusionRange' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_DhcpServerExclusionRange' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,158 +34,432 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -function Invoke-TestCleanup -{ +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + Restore-TestEnvironment -TestEnvironment $script:testEnvironment + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force + + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force } -Invoke-TestSetup +Describe 'DhcpServerExclusionRange\Get-TargetResource' -Tag 'Get' { + Context 'When the exclusion range exists' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'ScopeId' + } -MockWith { + return [IPAddress] '10.1.1.0' + } -try -{ - InModuleScope $script:dscResourceName { - $scopeId = '10.1.1.0' - $ipStartRange = '10.1.1.10' - $ipEndRange = '10.1.1.20' - $addressFamily = 'IPv4' - $ensure = 'Present' + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } - $testParams = @{ - ScopeId = $scopeId - IPStartRange = $ipStartRange - IPEndRange = $ipEndRange - AddressFamily = $addressFamily - } + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.20' + } - $badRangeParams = @{ - ScopeId = $scopeId - IPStartRange = $ipEndRange - IPEndRange = $ipStartRange - AddressFamily = $addressFamily - Ensure = $ensure + Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith { + return @( + @{ + ScopeId = '10.1.1.0' + StartRange = [IPAddress] '10.1.1.10' + EndRange = [IPAddress] '10.1.1.20' + } + ) + } } - $getFakeDhcpExclusionRange = { - return @( - [PSCustomObject] @{ - ScopeId = $scopeId - StartRange = [IPAddress]$ipStartRange - EndRange = [IPAddress]$ipEndRange - } - ) - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $getFakeDhcpExclusionRangeBadRange = { - return @( - [PSCustomObject] @{ - ScopeId = $scopeId - IPStartRange = [IPAddress]$ipEndRange - IPEndRange = [IPAddress]$ipStartRange + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' } - ) + + $result = Get-TargetResource @testParams + + $result | Should -BeOfType [System.Collections.Hashtable] + $result.ScopeId | Should -Be $testParams.ScopeId + $result.IPStartRange | Should -Be $testParams.IPStartRange + $result.IPEndRange | Should -Be $testParams.IPEndRange + $result.AddressFamily | Should -Be $testParams.AddressFamily + $result.Ensure | Should -Be 'Present' + } } + } - Describe 'DhcpServerExclusionRange\Get-TargetResource' { - Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith $getFakeDhcpExclusionRange + Context 'When the exclusion range does not exist' { + BeforeAll { Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'ScopeId' + } -MockWith { + return [IPAddress] '10.1.1.0' + } - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - $result = Get-TargetResource @testParams + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } - Assert-MockCalled -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.20' } - It 'Returns a "System.Collections.Hashtable" object type' { + Mock -CommandName Get-DhcpServerv4ExclusionRange + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' + } + $result = Get-TargetResource @testParams + $result | Should -BeOfType [System.Collections.Hashtable] + $result.ScopeId | Should -Be $testParams.ScopeId + # Key properties should be returned?? + #$result.IPStartRange | Should -Be $testParams.IPStartRange + #$result.IPEndRange | Should -Be $testParams.IPEndRange + + $result.IPStartRange | Should -BeNullOrEmpty + $result.IPEndRange | Should -BeNullOrEmpty + $result.AddressFamily | Should -Be $testParams.AddressFamily + $result.Ensure | Should -Be 'Absent' } + } + } - It 'Returns all correct values' { - Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith $getFakeDhcpExclusionRange + Context 'When the exclusion range is invalid' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'ScopeId' + } -MockWith { + return [IPAddress] '10.1.1.0' + } - $result = Get-TargetResource @testParams - $result.Ensure | Should -Be $ensure - $result.ScopeId | Should -Be $scopeId - $result.IPStartRange | Should -Be $ipStartRange - $result.IPEndRange | Should -Be $ipEndRange - $result.AddressFamily | Should -Be $addressFamily + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.20' } - It 'Returns the properties as $null when the exclusion does not exist' { - Mock -CommandName Get-DhcpServerv4ExclusionRange { return $null } + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } + } - $result = Get-TargetResource @testParams - $result.Ensure | Should -Be 'Absent' - $result.ScopeId | Should -Be $scopeId - $result.IPStartRange | Should -Be $null - $result.IPEndRange | Should -Be $null - $result.AddressFamily | Should -Be $addressFamily + It 'Should throw the correct exception' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.20' + IPEndRange = '10.1.1.10' + AddressFamily = 'IPv4' + } + + $errorMessageParams = @{ + ArgumentName = 'StartRange' + Message = $script:localizedData.InvalidStartAndEndRange + } + + $errorMessage = Get-InvalidArgumentRecord @errorMessageParams + + { Get-TargetResource @testParams } | Should -Throw -ExpectedMessage $errorMessage } } + } +} - Describe 'DhcpServerExclusionRange\Test-TargetResource' { - Mock -CommandName Assert-Module +Describe 'DhcpServerExclusionRange\Test-TargetResource' -Tag 'Test' { + Context 'When the resource exists' { + Context 'When the resource should exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } - It 'Returns a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith $getFakeDhcpExclusionRange + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.20' + } - $result = Test-TargetResource @testParams -Ensure 'Present' - $result | Should -BeOfType [System.Boolean] + Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith { + return @( + @{ + ScopeId = '10.1.1.0' + StartRange = [IPAddress] '10.1.1.10' + EndRange = [IPAddress] '10.1.1.20' + } + ) + } } - It 'Returns $true when the exclusion exists and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith $getFakeDhcpExclusionRange + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' + Ensure = 'Present' + } - $result = Test-TargetResource @testParams -Ensure 'Present' - $result | Should -Be $true + Test-TargetResource @testParams | Should -BeTrue + } } + } - It 'Returns $false when the exclusion does not exist and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4ExclusionRange { return $null } + Context 'When the resource should not exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } + + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.20' + } - $result = Test-TargetResource @testParams -Ensure 'Present' - $result | Should -Be $false + Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith { + return @( + @{ + ScopeId = '10.1.1.0' + StartRange = [IPAddress] '10.1.1.10' + EndRange = [IPAddress] '10.1.1.20' + } + ) + } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' + Ensure = 'Absent' + } + + Test-TargetResource @testParams | Should -BeFalse + } + } + } + } + + Context 'When the resource does not exist' { + Context 'When the resource should exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } + + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.20' + } + + Mock -CommandName Get-DhcpServerv4ExclusionRange + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' + Ensure = 'Present' + } + + Test-TargetResource @testParams | Should -BeFalse + } } + } + + Context 'When the resource should not exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } - It 'Returns $false when the exclusion exists and Ensure = Absent ' { - Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith $getFakeDhcpExclusionRange + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.20' + } - $result = Test-TargetResource @testParams -Ensure 'Absent' - $result | Should -Be $false + Mock -CommandName Get-DhcpServerv4ExclusionRange } - It 'Throws RangeNotCorrect exception when the start range is greater than the end range' { - { Test-TargetResource @badRangeParams } | Should -Throw 'StartRange must be less than EndRange' + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' + Ensure = 'Absent' + } + + Test-TargetResource @testParams | Should -BeTrue + } } } + } - Describe 'DhcpServerExclusionRange\Set-TargetResource' { + Context 'When the exclusion range is invalid' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'StartRange' + } -MockWith { + return [IPAddress] '10.1.1.20' + } + + Mock -CommandName Get-ValidIpAddress -ParameterFilter { + $ParameterName -eq 'EndRange' + } -MockWith { + return [IPAddress] '10.1.1.10' + } + } + + It 'Should throw the correct exception' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.20' + IPEndRange = '10.1.1.10' + AddressFamily = 'IPv4' + Ensure = 'Present' + } + + $errorMessageParams = @{ + ArgumentName = 'StartRange' + Message = $script:localizedData.InvalidStartAndEndRange + } + + $errorMessage = Get-InvalidArgumentRecord @errorMessageParams + + { Test-TargetResource @testParams } | Should -Throw -ExpectedMessage $errorMessage + } + } + } +} + +Describe 'DhcpServerExclusionRange\Set-TargetResource' -Tag 'Set' { + Context 'When the exclusion range should be created' { + BeforeAll { Mock -CommandName Assert-Module Mock -CommandName Add-DhcpServerv4ExclusionRange - Mock -CommandName Remove-DhcpServerv4ExclusionRange + } + + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - It 'Should call "Add-DhcpServerv4ExclusionRange" when "Ensure" = "Present" and exclusion does not exist' { - Mock -CommandName Get-DhcpServerv4ExclusionRange { return $null } + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' + Ensure = 'Present' + } - Set-TargetResource @testParams -Ensure 'Present' - Assert-MockCalled -CommandName Add-DhcpServerv4ExclusionRange + Set-TargetResource @testParams } - It 'Should call "Remove-DhcpServerv4ExclusionRange" when "Ensure" = "Absent" and exclusion does exist' { - Mock -CommandName Get-DhcpServerv4ExclusionRange -MockWith $getFakeDhcpExclusionRange + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4ExclusionRange -Exactly -Times 1 -Scope It + } + } + + Context 'When the exclusion range should be created' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Remove-DhcpServerv4ExclusionRange + } + + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Set-TargetResource @testParams -Ensure 'Absent' - Assert-MockCalled -CommandName Remove-DhcpServerv4ExclusionRange + $testParams = @{ + ScopeId = '10.1.1.0' + IPStartRange = '10.1.1.10' + IPEndRange = '10.1.1.20' + AddressFamily = 'IPv4' + Ensure = 'Absent' + } + + Set-TargetResource @testParams } + + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4ExclusionRange -Exactly -Times 1 -Scope It } } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DSC_DhcpServerOptionValue.Tests.ps1 b/tests/Unit/DSC_DhcpServerOptionValue.Tests.ps1 index 8d82d13..7818947 100644 --- a/tests/Unit/DSC_DhcpServerOptionValue.Tests.ps1 +++ b/tests/Unit/DSC_DhcpServerOptionValue.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_DhcpServerOptionValue' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_DhcpServerOptionValue' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,195 +34,143 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking -} + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - $optionId = 67 - $value = @('test Value') - $vendorClass = '' - $userClass = '' - $addressFamily = 'IPv4' - $ensure = 'Present' - - $testParams = @{ - OptionId = $optionId - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - Verbose = $true - } - - $getFakeDhcpServerv4OptionValue = { - return @{ - OptionId = $optionId - Value = $value - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } - } - - $getFakeDhcpServerv4OptionValueID168 = { - return @{ - OptionId = 168 - Value = $value - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } - } - - $getFakeDhcpServerv4OptionValueDifferentValue = { - return @{ - OptionId = $optionId - Value = @('DifferentValue') - VendorClass = $vendorClass - UserClass = $userClass - AddressFamily = $addressFamily - } - } - - Describe 'DSC_DhcpPolicyOptionValue\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - Assert-MockCalled -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } - - It 'Returns a "System.Collections.Hashtable" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result | Should -BeOfType [System.Collections.Hashtable] - } - - It 'Returns "Absent" when the option value does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Get-TargetResource @testParams - - $result.Ensure | Should -Be 'Absent' - } +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') - It 'Returns all correct values' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpServerv4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' + Restore-TestEnvironment -TestEnvironment $script:testEnvironment - $result = Get-TargetResource @testParams + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force - $result.Ensure | Should -Be $ensure - $result.OptionId | Should -Be $optionId - $result.Value | Should -Be @('DifferentValue') - $result.VendorClass | Should -Be $vendorClass - $result.UserClass | Should -Be $userClass - $result.AddressFamily | Should -Be $addressFamily - } + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - It 'Returns the properties as $null when the option does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' +$optionId = 67 +$value = @('test Value') +$vendorClass = '' +$userClass = '' +$addressFamily = 'IPv4' +$ensure = 'Present' + +$testParams = @{ + OptionId = $optionId + VendorClass = $vendorClass + UserClass = $userClass + AddressFamily = $addressFamily + Verbose = $true +} - $result = Get-TargetResource @testParams - $result.Ensure | Should -Be 'Absent' - $result.OptionId | Should -Be $null - $result.PolicyName | Should -Be $null - $result.Value | Should -Be $null - $result.VendorClass | Should -Be $null - $result.AddressFamily | Should -Be $null +Describe 'DSC_DhcpServerOptionValue\Get-TargetResource' -Tag 'Get' { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq 'Server' + } -MockWith { + @{ + ApplyTo = 'Server' + ReservedIP = '10.1.1.100' + UserClass = 'AClass' + OptionId = 67 + Value = @('test Value') + VendorClass = '' + ScopeId = '10.1.1.0' + PolicyName = 'Test Policy' + AddressFamily = 'IPv4' + Ensure = 'Present' } } + } + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Describe 'DSC_DhcpPolicyOptionValue\Test-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' + $testParams = @{ + OptionId = 67 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' } - It 'Returns a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value - - $result | Should -BeOfType [System.Boolean] - } + $result = Get-TargetResource @testParams - It 'Returns $true when the option exists and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' + $result | Should -BeOfType [System.Collections.Hashtable] + $result.Ensure | Should -Be 'Present' + $result.OptionId | Should -Be 67 + $result.Value | Should -Be @('test Value') + $result.VendorClass | Should -Be '' + $result.UserClass | Should -Be 'AClass' + $result.AddressFamily | Should -Be 'IPv4' - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value + $result.ApplyTo | Should -BeNullOrEmpty + $result.PolicyName | Should -BeNullOrEmpty + $result.ReservedIP | Should -BeNullOrEmpty + $result.ScopeId | Should -BeNullOrEmpty + } - $result | Should -Be $true - } + Should -Invoke -CommandName Get-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - It 'Returns $false when the option does not exist and Ensure = Present' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' +Describe 'DSC_DhcpServerOptionValue\Test-TargetResource' -Tag 'Test' { + BeforeAll { + Mock -CommandName Test-TargetResourceHelper -MockWith { + return $true + } + } - $result = Test-TargetResource @testParams -Ensure 'Present' -Value $value + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result | Should -Be $false + $testParams = @{ + OptionId = 67 + Value = @('test Value') + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + Ensure = 'Present' } - It 'Returns $false when the option exists and Ensure = Absent ' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - $result = Test-TargetResource @testParams -Ensure 'Absent' -Value $value + $result = Test-TargetResource @testParams - $result | Should -Be $false - } + $result | Should -BeTrue } - Describe 'DSC_DhcpPolicyOptionValue\Set-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module -ModuleName 'DhcpServerDsc.OptionValueHelper' - } - - Mock -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - Mock -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and definition does not exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { return $null } -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Should -Invoke -CommandName Test-TargetResourceHelper -Exactly -Times 1 -Scope It + } +} - It 'Should call "Remove-DhcpServerv4OptionValue" when "Ensure" = "Absent" and Definition does exist' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $GetFakeDhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' +Describe 'DSC_DhcpServerOptionValue\Set-TargetResource' -Tag 'Set' { + BeforeAll { + Mock -CommandName Set-TargetResourceHelper + } - Set-TargetResource @testParams -Ensure 'Absent' -Value $value + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It + $testParams = @{ + OptionId = 67 + Value = @('test Value') + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + Ensure = 'Present' } - It 'Should call "Set-DhcpServerv4OptionValue" when "Ensure" = "Present" and option value is different' { - Mock -CommandName Get-DhcpServerv4OptionValue -MockWith $getFakeDhcpServerv4OptionValueDifferentValue -ModuleName 'DhcpServerDsc.OptionValueHelper' - - Set-TargetResource @testParams -Ensure 'Present' -Value $value - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionValue -ModuleName 'DhcpServerDsc.OptionValueHelper' -Exactly -Times 1 -Scope It - } + Set-TargetResource @testParams } + + Should -Invoke -CommandName Set-TargetResourceHelper -Exactly -Times 1 -Scope It } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DSC_xDhcpServerAuthorization.Tests.ps1 b/tests/Unit/DSC_xDhcpServerAuthorization.Tests.ps1 index c2b58d6..2a72cf5 100644 --- a/tests/Unit/DSC_xDhcpServerAuthorization.Tests.ps1 +++ b/tests/Unit/DSC_xDhcpServerAuthorization.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_xDhcpServerAuthorization' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_xDhcpServerAuthorization' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,250 +34,317 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -function Invoke-TestCleanup -{ +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - # Test TargetResource parameters with Ensure = 'Present'. - $testPresentParams = @{ - IsSingleInstance = 'Yes' - Ensure = 'Present' - DnsName = 'test1.contoso.com' - IPAddress = '192.168.1.1' - Verbose = $true - } + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force - # Test TargetResource parameters with Ensure = 'Absent'. - $testAbsentParams = @{ - IsSingleInstance = 'Yes' - Ensure = 'Absent' - DnsName = 'test1.contoso.com' - IPAddress = '192.168.1.1' - Verbose = $true - } + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - <# - Authorized server list with test1.contoso.com authorized. - This needs to be a PSCustomObject to work with ValueFromPipelineByPropertyName - when calling cmdlet Remove-DhcpServerInDC. - #> - $fakeDhcpServersPresent = @( - [PSCustomObject] @{ - IPAddress = '192.168.1.1' - DnsName = 'test1.contoso.com' - }, - [PSCustomObject] @{ - IPAddress = '192.168.1.2' - DnsName = 'test2.contoso.com' - }, - [PSCustomObject] @{ - IPAddress = '192.168.1.3' - DnsName = 'test3.contoso.com' - } - ) - - # Authorized server list with test1.contoso.com not authorized - $fakeDhcpServersAbsent = @( - @{ - IPAddress = '192.168.1.2' - DnsName = 'test2.contoso.com' - }, - @{ - IPAddress = '192.168.1.3' - DnsName = 'test3.contoso.com' - } - ) - - # Authorized server list with mismatched DnsName, but matched IPAddress - $fakeDhcpServersMismatchDnsName = @( - @{ - IPAddress = '192.168.1.1' - DnsName = 'test11.contoso.com' - }, - @{ - IPAddress = '192.168.1.2' - DnsName = 'test2.contoso.com' - }, - @{ - IPAddress = '192.168.1.3' - DnsName = 'test3.contoso.com' +Describe 'DSC_xDhcpServerAuthorization\Get-TargetResource' -Tag 'Get' { + Context 'When the resource exists' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIPAddress -MockWith { + return [IPAddress] '192.168.1.1' } - ) - - # Authorized server list with mismatched IPAddress, but matched DnsName - $fakeDhcpServersMismatchIPAddress = @( - @{ - IPAddress = '192.168.1.11' - DnsName = 'test1.contoso.com' - }, - @{ - IPAddress = '192.168.1.2' - DnsName = 'test2.contoso.com' - }, - @{ - IPAddress = '192.168.1.3' - DnsName = 'test3.contoso.com' - } - ) - Describe 'DSC_xDhcpServerAuthorization\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerInDC -MockWith { + return @( + @{ + IPAddress = '192.168.1.1' + DnsName = 'test1.contoso.com' + }, + @{ + IPAddress = '192.168.1.2' + DnsName = 'test2.contoso.com' + }, + @{ + IPAddress = '192.168.1.3' + DnsName = 'test3.contoso.com' + } + ) } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - It 'Returns a [System.Collection.Hashtable] type' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersPresent + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Present' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' } - $result = Get-TargetResource @testPresentParams + $result = Get-TargetResource @testParams - $result -is [System.Collections.Hashtable] | Should -Be $true + $result.DnsName | Should -Be $testParams.DnsName + $result.IPAddress | Should -Be $testParams.IPAddress + $result.Ensure | Should -Be 'Present' } + } + } - It 'Returns Ensure is Present when DHCP server authorization exists' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersPresent - } + Context 'When the resource does not exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIPAddress -MockWith { + return [IPAddress] '192.168.1.1' + } - $result = Get-TargetResource @testPresentParams + Mock -CommandName Get-DhcpServerInDC + } - $result.Ensure | Should -Be 'Present' - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - It 'Returns Ensure is Absent when DHCP server authorization does not exist' { - Mock -CommandName Get-DhcpServerInDC + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Present' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' + } - $result = Get-TargetResource @testPresentParams + $result = Get-TargetResource @testParams + $result.DnsName | Should -BeNullOrEmpty + $result.IPAddress | Should -BeNullOrEmpty $result.Ensure | Should -Be 'Absent' } - } + } +} - Describe 'DSC_xDhcpServerAuthorization\Test-TargetResource' { +Describe 'DSC_xDhcpServerAuthorization\Test-TargetResource' -Tag 'Test' { + Context 'When the resource is in the desired state' { + Context 'When the resource exists' { BeforeAll { - Mock -CommandName Assert-Module + Mock -CommandName Get-TargetResource -MockWith { + return @{ + Ensure = 'Present' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' + } + } } - It 'Returns a [System.Boolean] type' { - Mock Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersPresent - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result = Test-TargetResource @testPresentParams + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Present' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' + } - $result -is [System.Boolean] | Should -Be $true + Test-TargetResource @testParams | Should -BeTrue + } } + } - It 'Fails when DHCP Server authorization does not exist and Ensure is Present' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersAbsent - } - Test-TargetResource @testPresentParams | Should -Be $false + Context 'When the resource should not exist' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + Ensure = 'Absent' + } + } } - It 'Fails when DHCP Server authorization does exist and Ensure is Absent' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersPresent - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Test-TargetResource @testAbsentParams | Should -Be $false - } + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Absent' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' + } - It 'Fails when DHCP Server authorization does exist, Ensure is Present but DnsName is wrong' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersMismatchDnsName + Test-TargetResource @testParams | Should -BeTrue } - - Test-TargetResource @testPresentParams | Should -Be $false } + } + } - It 'Fails when DHCP Server authorization does exist, Ensure is Present but IPAddress is wrong' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersMismatchIPAddress + Context 'When the resource is not in the desired state' { + BeforeDiscovery { + $testCases = @( + @{ + Property = 'DnsName' + Value = 'test2.contoso.com' } + @{ + Property = 'IPAddress' + Value = '192.168.10.1' + } + ) + } - Test-TargetResource @testPresentParams | Should -Be $false - } - - It 'Passes when DHCP Server authorization does exist and Ensure is Present' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersPresent + Context 'When the property is incorrect' -ForEach $testCases { + BeforeAll { + $mockGetTargetResource = @{ + Ensure = 'Present' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' } - $result = Test-TargetResource @testPresentParams + $mockGetTargetResource.$Property = $Value - $result -is [System.Boolean] | Should -Be $true + Mock -CommandName Get-TargetResource -MockWith { + return $mockGetTargetResource + } } - It 'Passes when DHCP Server authorization does not exist and Ensure is Absent' { - Mock Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersAbsent - } + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 - $result = Test-TargetResource @testAbsentParams + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Present' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' + } - $result -is [System.Boolean] | Should -Be $true + $result = Test-TargetResource @testParams + $result | Should -BeFalse + } } } + } +} - Describe 'DSC_xDhcpServerAuthorization\Set-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module - } +Describe 'DSC_xDhcpServerAuthorization\Set-TargetResource' -Tag 'Set' { + Context 'When the resource should be created' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Add-DhcpServerInDc + } - It 'Calls Add-DhcpServerInDc when Ensure is Present' { - Mock -CommandName Add-DhcpServerInDC + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Set-TargetResource @testPresentParams + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Present' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' + } - Assert-MockCalled -CommandName Add-DhcpServerInDC -Exactly -Times 1 -Scope It + Set-TargetResource @testParams } - It 'Calls Remove-DhcpServerInDc when Ensure is Present' { - Mock -CommandName Get-DhcpServerInDC -MockWith { - return $fakeDhcpServersPresent + + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerInDc -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource should be removed' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerInDc -MockWith { + return @( + @{ + IPAddress = '192.168.1.1' + DnsName = 'test1.contoso.com' + }, + @{ + IPAddress = '192.168.1.2' + DnsName = 'test2.contoso.com' + }, + @{ + IPAddress = '192.168.1.3' + DnsName = 'test3.contoso.com' + } + ) + } + + Mock -CommandName Remove-DhcpServerInDc + } + + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + IsSingleInstance = 'Yes' + Ensure = 'Absent' + DnsName = 'test1.contoso.com' + IPAddress = '192.168.1.1' } - Mock -CommandName Remove-DhcpServerInDC + Set-TargetResource @testParams + } - Set-TargetResource @testAbsentParams + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerInDc -Exactly -Times 1 -Scope It + # TODO: Pipeline call is not invoking. + #Should -Invoke -CommandName Remove-DhcpServerInDc -Exactly -Times 1 -Scope It + } + } +} - Assert-MockCalled -CommandName Remove-DhcpServerInDC -Exactly -Times 1 -Scope It +Describe 'DSC_xDhcpServerAuthorization\Get-IPv4Address' -Tag 'Helper' { + BeforeAll { + Mock -CommandName Get-CimInstance -MockWith { + return New-CimInstance -ClassName 'Win32_NetworkAdapterConfiguration' -Namespace 'root\CIMV2' -ClientOnly -Property @{ + IPEnabled = 'True' + IPAddress = '10.1.1.10' } } + } - Describe 'DSC_xDhcpServerAuthorization\Get-IPv4Address' { - It 'Returns a IPv4 address' { - $result = Get-IPv4Address -Verbose | Select-Object -First 1 + It 'Returns a IPv4 address' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result -match '\d+\.\d+\.\d+\.\d+' | Should -Be $true - } + $result = Get-IPv4Address | Select-Object -First 1 + $result | Should -Be '10.1.1.10' } + } +} - Describe 'DSC_xDhcpServerAuthorization\Get-Hostname' { - It 'Returns at least the current NetBIOS name' { - $hostname = [System.Net.Dns]::GetHostname() +Describe 'DSC_xDhcpServerAuthorization\Get-Hostname' -Tag 'Helper' { + Context 'When a DomainName exists' { + # TODO: Mock a .NET type + # It 'Should return the correct result' { + # InModuleScope -ScriptBlock { + # Set-StrictMode -Version 1.0 - $result = Get-Hostname -Verbose + # Get-HostName | Should -Be ('{0}.{1}' -f (Get-ComputerName), $env:USERDNSDOMAIN) + # } + # } + } + + Context 'When a DomainName does not exist' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result -match $hostname | Should -Be $true + Get-HostName | Should -Be (Get-ComputerName) } } - } #end InModuleScope -} -finally -{ - Invoke-TestCleanup + } } diff --git a/tests/Unit/DSC_xDhcpServerClass.Tests.ps1 b/tests/Unit/DSC_xDhcpServerClass.Tests.ps1 index 2f9564d..440acaa 100644 --- a/tests/Unit/DSC_xDhcpServerClass.Tests.ps1 +++ b/tests/Unit/DSC_xDhcpServerClass.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_xDhcpServerClass' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_xDhcpServerClass' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,145 +34,339 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -function Invoke-TestCleanup -{ +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} -Invoke-TestSetup + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force -try -{ - InModuleScope $script:dscResourceName { - $testClassName = 'Test Class' - $testClassType = 'Vendor' - $testAsciiData = 'test data' - $testClassDescription = 'test class description' - $testClassAddressFamily = 'IPv4' + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - $testParams = @{ - Name = $testClassName - Type = $testClassType - AsciiData = $testAsciiData - AddressFamily = 'IPv4' - Description = $testClassDescription - Verbose = $true +Describe 'DSC_xDhcpServerClass\Get-TargetResource' -Tag 'Get' { + Context 'When the resource exists' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4Class -MockWith { + return @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + Description = 'test class description' + AddressFamily = 'IPv4' + } + } } - $fakeDhcpServerClass = [PSCustomObject] @{ - Name = $testClassName - Type = $testClassType - AsciiData = $testAsciiData - Description = $testClassDescription - AddressFamily = $testClassAddressFamily - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Describe 'DSC_xDhcpServerClass\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Present' + + } + + $result = Get-TargetResource @testParams + + $result.Name | Should -Be $testParams.Name + $result.Type | Should -Be $testParams.Type + $result.AsciiData | Should -Be $testParams.AsciiData + $result.Description | Should -Be $testParams.Description + $result.AddressFamily | Should -Be $testParams.AddressFamily } + } + } - It 'Calls "Assert-Module" to ensure "DHCPServer" module is available' { - Mock -CommandName Get-DhcpServerv4Class -MockWith { - return $fakeDhcpServerClass + Context 'When the resource does not exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4Class + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Present' } - $result = Get-TargetResource @testParams -Ensure Present + $result = Get-TargetResource @testParams - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { - $ModuleName -eq 'DHCPServer' - } -Exactly -Times 1 -Scope It + $result.Name | Should -BeNullOrEmpty + $result.Type | Should -BeNullOrEmpty + $result.AsciiData | Should -BeNullOrEmpty + $result.Description | Should -BeNullOrEmpty + $result.AddressFamily | Should -BeNullOrEmpty } + } + } +} - It 'Returns a "System.Collections.Hashtable" object type' { +Describe 'DSC_xDhcpServerClass\Test-TargetResource' -Tag 'Test' { + Context 'When the resource is in the desired state' { + Context 'When the resource should be present' { + BeforeAll { Mock -CommandName Get-DhcpServerv4Class -MockWith { - return $fakeDhcpServerClass + return @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + Description = 'test class description' + AddressFamily = 'IPv4' + } } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result = Get-TargetResource @testParams -Ensure Present + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Present' + } - $result -is [System.Collections.Hashtable] | Should -Be $true + Test-TargetResource @testParams | Should -BeTrue + } } } - Describe 'DSC_xDhcpServerClass\Test-TargetResource' { + Context 'When the resource should be absent' { BeforeAll { - Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4Class } - It 'Returns a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4Class -MockWith { - return $fakeDhcpServerClass - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result = Test-TargetResource @testParams -Ensure Present + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Absent' + } - $result -is [System.Boolean] | Should -Be $true + Test-TargetResource @testParams | Should -BeTrue + } } + } + } - It 'Passes when all parameters are correct' { - Mock -CommandName Get-DhcpServerv4Class { - return $fakeDhcpServerClass + Context 'When the resource is not in the desired state' { + Context 'When one property is incorrect' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Class -MockWith { + return @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + Description = 'test class description' + AddressFamily = 'IPv4' + } } + } - $result = Test-TargetResource @testParams -Ensure Present + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $result | Should -Be $true - } + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description error' + Ensure = 'Present' + } + Test-TargetResource @testParams | Should -BeFalse + } + } } - Describe 'DSC_xDhcpServerClass\Set-TargetResource' { + Context 'When the resource should exist but does not' { BeforeAll { - Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4Class + } + + It 'Should return $false' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Present' + } + + Test-TargetResource @testParams | Should -BeFalse + } } + } - It 'Calls "Add-DhcpServerv4Class" when "Ensure" = "Present" and class does not exist' { + Context 'When the resource should not exist but does' { + BeforeAll { Mock -CommandName Get-DhcpServerv4Class -MockWith { - return $null + return @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + Description = 'test class description' + AddressFamily = 'IPv4' + } } + } - Mock -CommandName Set-DhcpServerv4Class - Mock -CommandName Add-DhcpServerv4Class + It 'Should return $false' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Set-TargetResource @testParams -Ensure Present + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Absent' + } - Assert-MockCalled -CommandName Add-DhcpServerv4Class -Exactly -Times 1 -Scope It + Test-TargetResource @testParams | Should -BeFalse + } } + } + } +} - It 'Calls "Remove-DhcpServerv4Class" when "Ensure" = "Absent" and scope does exist' { - Mock -CommandName Get-DhcpServerv4Class -MockWith { - return $fakeDhcpServerClass +Describe 'DSC_xDhcpServerClass\Set-TargetResource' { + Context 'When a resource needs creating' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Class + Mock -CommandName Add-DhcpServerv4Class + } + + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Present' } - Mock -CommandName Remove-DhcpServerv4Class + Set-TargetResource @testParams + } - Set-TargetResource @testParams -Ensure 'Absent' + Should -Invoke -CommandName Get-DhcpServerv4Class -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Class -Exactly -Times 1 -Scope It + } + } - Assert-MockCalled -CommandName Remove-DhcpServerv4Class -Exactly -Times 1 -Scope It + Context 'When a resource needs updating' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Class -MockWith { + return @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + Description = 'test class description' + AddressFamily = 'IPv4' + } } - It 'Calls Set-DhcpServerv4Class when asciidata changes' { - Mock -CommandName Get-DhcpServerv4Class -MockWith { - return $fakeDhcpServerClass + Mock -CommandName Set-DhcpServerv4Class + } + + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Present' } - Mock -CommandName Set-DhcpServerv4Class + Set-TargetResource @testParams + } + + Should -Invoke -CommandName Get-DhcpServerv4Class -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Class -Exactly -Times 1 -Scope It + } + } + + Context 'When a resource needs deleting' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Class -MockWith { + return @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + Description = 'test class description' + AddressFamily = 'IPv4' + } + } - $testParams.AsciiData = 'differentdata' + Mock -CommandName Remove-DhcpServerv4Class + } - Set-TargetResource @testParams -Ensure 'Present' + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + Name = 'Test Class' + Type = 'Vendor' + AsciiData = 'test data' + AddressFamily = 'IPv4' + Description = 'test class description' + Ensure = 'Absent' + } - Assert-MockCalled -CommandName Set-DhcpServerv4Class -Exactly -Times 1 -Scope It + Set-TargetResource @testParams } + + Should -Invoke -CommandName Get-DhcpServerv4Class -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Class -Exactly -Times 1 -Scope It } - } #end InModuleScope -} -finally -{ - Invoke-TestCleanup + } } diff --git a/tests/Unit/DSC_xDhcpServerOptionDefinition.Tests.ps1 b/tests/Unit/DSC_xDhcpServerOptionDefinition.Tests.ps1 index b2b4a4e..b0b3c8f 100644 --- a/tests/Unit/DSC_xDhcpServerOptionDefinition.Tests.ps1 +++ b/tests/Unit/DSC_xDhcpServerOptionDefinition.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_xDhcpServerOptionDefinition' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_xDhcpServerOptionDefinition' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,412 +34,509 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -function Invoke-TestCleanup -{ +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + Restore-TestEnvironment -TestEnvironment $script:testEnvironment + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force + + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force } -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - $optionId = 22 - $name = 'Test name' - $addressFamily = 'IPv4' - $description = 'Test Description' - $type = 'IPv4Address' - $vendorClass = '' - $multiValued = $false - $defaultValue = '1.2.3.4' - - $testParams = @{ - OptionId = $optionId - Name = $name - AddressFamily = $addressFamily - Description = $description - Type = $type - VendorClass = $vendorClass - MultiValued = $multiValued - Verbose = $true +Describe 'DSC_xDhcpServerOptionDefinition\Get-TargetResource' -Tag 'Get' { + Context 'When the resource exists' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { + return @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = '' + MultiValued = $false + DefaultValue = '1.2.3.4' + } + } } - $fakeDhcpServerv4OptionDefinition = [PSCustomObject] @{ - OptionId = $optionId - Name = $name - AddressFamily = $addressFamily - Description = $description - Type = $type - VendorClass = $vendorClass - MultiValued = $multiValued - DefaultValue = $defaultValue - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Describe 'DSC_xDhcpServerOptionDefinition\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module - Mock -CommandName Set-DhcpServerv4OptionDefinition - Mock -CommandName Add-DhcpServerv4OptionDefinition - Mock -CommandName Remove-DhcpServerv4OptionDefinition - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition + $testParams = @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Type = 'IPv4Address' + VendorClass = '' } + + $result = Get-TargetResource @testParams + + $result.OptionId | Should -Be $testParams.OptionId + $result.Name | Should -Be $testParams.Name + $result.AddressFamily | Should -Be $testParams.AddressFamily + $result.Description | Should -Be 'Test Description' + $result.Type | Should -Be $testParams.Type + $result.VendorClass | Should -Be $testParams.VendorClass + $result.MultiValued | Should -BeFalse + $result.DefaultValue | Should -Be '1.2.3.4' + $result.Ensure | Should -Be 'Present' } + } + } - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - $result = Get-TargetResource -OptionId $OptionId -Name $Name -Type $Type -VendorClass $VendorClass -AddressFamily 'IPv4' -Ensure 'Present' -Verbose + Context 'When the resource does not exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-DhcpServerv4OptionDefinition + } - Assert-MockCalled -CommandName Assert-Module -Exactly -Times 1 -Scope It - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - It 'Returns a "System.Collections.Hashtable" object type' { - $result = Get-TargetResource -OptionId $OptionId -Name $Name -Type $Type -VendorClass $VendorClass -AddressFamily 'IPv4' -Ensure 'Present' -Verbose + $testParams = @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Type = 'IPv4Address' + VendorClass = '' + } - $result -is [System.Collections.Hashtable] | Should -Be $true + $result = Get-TargetResource @testParams + + $result.OptionId | Should -BeNullOrEmpty + $result.Name | Should -BeNullOrEmpty + $result.AddressFamily | Should -BeNullOrEmpty + $result.Description | Should -BeNullOrEmpty + $result.Type | Should -BeNullOrEmpty + $result.VendorClass | Should -BeNullOrEmpty + $result.MultiValued | Should -BeFalse + $result.DefaultValue | Should -BeNullOrEmpty + $result.Ensure | Should -Be 'Absent' } } + } +} - Describe 'DSC_xDhcpServerOptionDefinition\Test-TargetResource' { +Describe 'DSC_xDhcpServerOptionDefinition\Test-TargetResource' -Tag 'Test' { + Context 'When the system is in the desired state' { + Context 'When the configuration is absent' { BeforeAll { Mock -CommandName Assert-Module - - $mockOptionId = 22 - $mockName = 'Test name' - $mockAddressFamily = 'IPv4' - $mockDescription = 'Test Description' - $mockType = 'IPv4Address' - $mockVendorClass = 'MockVendorClass' - $mockDefaultValue = '1.2.3.4' - - $mockDefaultParameters = @{ - OptionId = $mockOptionId - Name = $mockName - VendorClass = $mockVendorClass - Type = $mockType - AddressFamily = $mockAddressFamily - DefaultValue = $mockDefaultValue + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = $null + Name = $null + AddressFamily = $null + Description = $null + Type = $null + VendorClass = $null + MultiValued = $false + DefaultValue = $null + Ensure = 'Absent' + } } } - Context 'When the system is in the desired state' { - Context 'When the configuration is absent' { - BeforeAll { - Mock -CommandName Get-TargetResource -MockWith { - return @{ - OptionId = $null - Name = $null - AddressFamily = $null - Description = $null - Type = $null - VendorClass = $null - MultiValued = $false - DefaultValue = $null - Ensure = 'Absent' - } - } - - $testTargetResourceParameters = $mockDefaultParameters.Clone() - $testTargetResourceParameters['Ensure'] = 'Absent' + It 'Should return the state as $true' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + VendorClass = 'MockVendorClass' + Type = 'IPv4Address' + AddressFamily = 'IPv4' + DefaultValue = '1.2.3.4' + Ensure = 'Absent' } - It 'Should return the state as $true' { - $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters - $testTargetResourceResult | Should -Be $true - } + $result = Test-TargetResource @testParams + $result | Should -BeTrue } + } + } + } - Context 'When the configuration is present' { - BeforeAll { - Mock -CommandName Get-TargetResource -MockWith { - return @{ - OptionId = $mockOptionId - Name = $mockName - AddressFamily = $mockAddressFamily - Description = $mockDescription - Type = $mockType - VendorClass = $mockVendorClass - MultiValued = $true - DefaultValue = $mockDefaultValue - Ensure = 'Present' - } - } - - $testTargetResourceParameters = $mockDefaultParameters.Clone() - $testTargetResourceParameters['Ensure'] = 'Present' - $testTargetResourceParameters['Description'] = $mockDescription - $testTargetResourceParameters['MultiValued'] = $true - $testTargetResourceParameters['DefaultValue'] = $mockDefaultValue - } - - It 'Should return the state as $true' { - $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters - $testTargetResourceResult | Should -Be $true - } + Context 'When the configuration is present' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = 22 + Name = 'Test name' + VendorClass = 'MockVendorClass' + Type = 'IPv4Address' + AddressFamily = 'IPv4' + DefaultValue = '1.2.3.4' + Description = 'Test Description' + MultiValued = $true + Ensure = 'Present' } } + } - Context 'When the system is not in the desired state' { - Context 'When the configuration should be absent' { - BeforeAll { - Mock -CommandName Get-TargetResource -MockWith { - return @{ - OptionId = $mockOptionId - Name = $mockName - AddressFamily = $mockAddressFamily - Description = $mockDescription - Type = $mockType - VendorClass = $mockVendorClass - MultiValued = $true - DefaultValue = $mockDefaultValue - Ensure = 'Present' - } - } - - $testTargetResourceParameters = $mockDefaultParameters.Clone() - $testTargetResourceParameters['Ensure'] = 'Absent' - } - - It 'Should return the state as $false' { - $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters - $testTargetResourceResult | Should -Be $false - } + It 'Should return the state as $true' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + VendorClass = 'MockVendorClass' + Type = 'IPv4Address' + AddressFamily = 'IPv4' + Description = 'Test Description' + MultiValued = $true + DefaultValue = '1.2.3.4' + Ensure = 'Present' } - Context 'When the configuration should be present' { - BeforeAll { - Mock -CommandName Get-TargetResource -MockWith { - return @{ - OptionId = $null - Name = $null - AddressFamily = $null - Description = $null - Type = $null - VendorClass = $null - MultiValued = $false - Ensure = 'Absent' - } - } - - $testTargetResourceParameters = $mockDefaultParameters.Clone() - $testTargetResourceParameters['Ensure'] = 'Present' - } + $result = Test-TargetResource @testParams + $result | Should -BeTrue + } + } + } - It 'Should return the state as $false' { - $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters - $testTargetResourceResult | Should -Be $false + Context 'When the system is not in the desired state' { + Context 'When the configuration should be absent' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = 'MockVendorClass' + MultiValued = $true + DefaultValue = '1.2.3.4' + Ensure = 'Present' } } + } - Context 'When a property is not in desired state' { - BeforeAll { - Mock -CommandName Get-TargetResource -MockWith { - return @{ - OptionId = $mockOptionId - Name = $mockName - AddressFamily = $mockAddressFamily - Description = $mockDescription - Type = $mockType - VendorClass = $mockVendorClass - MultiValued = $false - Ensure = 'Present' - } - } - - $testCases = @( - @{ - Property = 'Name' - } - @{ - Property = 'Description' - } - @{ - Property = 'Type' - } - @{ - Property = 'MultiValued' - } - ) + It 'Should return the state as $false' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + VendorClass = 'MockVendorClass' + Type = 'IPv4Address' + AddressFamily = 'IPv4' + DefaultValue = '1.2.3.4' + Ensure = 'Absent' } - BeforeEach { - $testTargetResourceParameters = $mockDefaultParameters.Clone() - $testTargetResourceParameters['Ensure'] = 'Present' - } - It 'Should return the state as $false when property is not in desired state' -TestCases $testCases { - param - ( - [Parameter()] - [System.String] - $Property - ) - - if ($Property -eq 'Type') - { - $testTargetResourceParameters[$Property] = 'EncapsulatedData' - } - else - { - # Mock with 1 as it can be converted to string, int, and boolean. - $testTargetResourceParameters[$Property] = 1 - } - - $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters - $testTargetResourceResult | Should -Be $false - } + $result = Test-TargetResource @testParams + $result | Should -BeFalse } } } - Describe 'DSC_xDhcpServerOptionDefinition\Set-TargetResource' { + Context 'When the configuration should be present' { BeforeAll { Mock -CommandName Assert-Module - } - - Mock -CommandName Set-DhcpServerv4OptionDefinition - Mock -CommandName Add-DhcpServerv4OptionDefinition - Mock -CommandName Remove-DhcpServerv4OptionDefinition - - It 'Should call "Add-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and definition does not exist' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $null + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = $null + Name = $null + AddressFamily = $null + Description = $null + Type = $null + VendorClass = $null + MultiValued = $false + Ensure = 'Absent' + } } + } - $TempParams = $testParams.Clone() - $TempParams.OptionId = 2 + It 'Should return the state as $false' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + VendorClass = 'MockVendorClass' + Type = 'IPv4Address' + AddressFamily = 'IPv4' + DefaultValue = '1.2.3.4' + Ensure = 'Present' + } - Set-TargetResource @TempParams -Ensure 'Present' - Assert-MockCalled Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It - } - - It 'Should call "Remove-DhcpServerv4OptionDefinition" when "Ensure" = "Absent" and Definition does exist' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition + $result = Test-TargetResource @testParams + $result | Should -BeFalse } + } + } - Set-TargetResource @testParams -Ensure 'Absent' - - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Context 'When a property is not in desired state' { + BeforeDiscovery { + $testCases = @( + @{ + Property = 'Name' + } + @{ + Property = 'Description' + } + @{ + Property = 'Type' + } + @{ + Property = 'MultiValued' + } + ) } - It 'Should call Set-DhcpServerv4OptionDefinition when "Ensure" = "Present" and Name or Description has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = 'MockVendorClass' + MultiValued = $false + Ensure = 'Present' + } } + } - $TempParams = $testParams.Clone() - $TempParams.Description = 'New Description' + It 'Should return the state as $false when property '''' is not in desired state' -TestCases $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + VendorClass = 'MockVendorClass' + Type = 'IPv4Address' + AddressFamily = 'IPv4' + DefaultValue = '1.2.3.4' + Ensure = 'Present' + } - Set-TargetResource @TempParams -Ensure 'Present' + if ($Property -eq 'Type') + { + $testParams[$Property] = 'EncapsulatedData' + } + else + { + # Mock with 1 as it can be converted to string, int, and boolean. + $testParams[$Property] = 1 + } - Assert-MockCalled -CommandName Set-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + $result = Test-TargetResource @testParams + $result | Should -BeFalse + } } + } + } +} - It 'Should call "Remove-DhcpServerv4OptionDefinition" and then "Add-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and Type, MultiValued, VendorClass has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition - } +Describe 'DSC_xDhcpServerOptionDefinition\Set-TargetResource' -Tag 'Set' { + Context 'When the resource does not exist' { + Context 'When the resource needs to be created' { + BeforeAll { + Mock -CommandName Get-TargetResource + Mock -CommandName Add-DhcpServerv4OptionDefinition + } - $TempParams = $testParams.Clone() - $TempParams.Type = 'Byte' + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = '' + DefaultValue = '1.2.3.4' + MultiValued = $false + } - Set-TargetResource @TempParams -Ensure 'Present' + Set-TargetResource @testParams + } - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It } + } + } - It 'Should call "Remove-DhcpServerv4OptionDefinition" and then "Add-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and Type has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition + Context 'When the resource does exist' { + Context 'When the resource needs to be removed' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = '' + MultiValued = $false + DefaultValue = '1.2.3.4' + } } - $TempParams = $testParams.Clone() - $TempParams.Type = 'Byte' - - Set-TargetResource @tempParams -Ensure 'Present' - - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Mock -CommandName Remove-DhcpServerv4OptionDefinition } - It 'Should call "Remove-DhcpServerv4OptionDefinition" and then "Add-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and MultiValued has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition - } + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = '' + MultiValued = $false + Ensure = 'Absent' + } - $TempParams = $testParams.Clone() - $TempParams.MultiValued = $true + Set-TargetResource @testParams + } - Set-TargetResource @TempParams -Ensure 'Present' + Should -Invoke -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + } + } - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Context 'When the resource needs to be re-added' { + BeforeDiscovery { + $testCases = @( + @{ + Property = 'Type' + Value = 'Byte' + } + @{ + Property = 'MultiValued' + Value = $true + } + @{ + Property = 'VendorClass' + Value = 'New VendorClass' + } + ) } - It 'Should call "Remove-DhcpServerv4OptionDefinition" and then "Add-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and VendorClass has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = '' + MultiValued = $false + DefaultValue = '1.2.3.4' + Ensure = 'Present' + } } - $TempParams = $testParams.Clone() - $TempParams.VendorClass = 'NewVendorClass' - - Set-TargetResource @TempParams -Ensure 'Present' - - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Mock -CommandName Remove-DhcpServerv4OptionDefinition + Mock -CommandName Add-DhcpServerv4OptionDefinition } - It 'Should call "Remove-DhcpServerv4OptionDefinition" and then "Add-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and VendorClass and Description has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition - } + It 'Should call the expected mocks for ''''' -ForEach $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = '' + MultiValued = $false + DefaultValue = '1.2.3.4' + Ensure = 'Present' + } - $TempParams = $testParams.Clone() - $TempParams.VendorClass = 'NewVendorClass' - $TempParams.Description = 'New Description' + $testParams.$Property = $Value - Set-TargetResource @TempParams -Ensure 'Present' + Set-TargetResource @testParams + } - Assert-MockCalled -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It } + } - It 'Should call "Set-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and Description has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition + Context 'When the resource needs to be updated' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'Test Description' + Type = 'IPv4Address' + VendorClass = '' + MultiValued = $false + DefaultValue = '1.2.3.4' + Ensure = 'Present' + } } - $TempParams = $testParams.Clone() - $TempParams.Description = 'New Description' - - Set-TargetResource @testParams -Ensure 'Present' - - Assert-MockCalled -CommandName Set-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Mock -CommandName Set-DhcpServerv4OptionDefinition } - It 'Should call "Set-DhcpServerv4OptionDefinition" when "Ensure" = "Present" and DefaultValue has changed' { - Mock -CommandName Get-DhcpServerv4OptionDefinition -MockWith { - return $fakeDhcpServerv4OptionDefinition - } - - $TempParams = $testParams.Clone() - $TempParams.DefaultValue = '1.2.3.5' + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + OptionId = 22 + Name = 'Test name' + AddressFamily = 'IPv4' + Description = 'New Description' + Type = 'IPv4Address' + VendorClass = '' + MultiValued = $false + DefaultValue = '1.2.3.4' + Ensure = 'Present' + } - Set-TargetResource @testParams -Ensure 'Present' + Set-TargetResource @testParams + } - Assert-MockCalled -CommandName Set-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-TargetResource -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4OptionDefinition -Exactly -Times 1 -Scope It } } } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DSC_xDhcpServerReservation.Tests.ps1 b/tests/Unit/DSC_xDhcpServerReservation.Tests.ps1 new file mode 100644 index 0000000..d054281 --- /dev/null +++ b/tests/Unit/DSC_xDhcpServerReservation.Tests.ps1 @@ -0,0 +1,595 @@ +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_xDhcpServerReservation' + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + Restore-TestEnvironment -TestEnvironment $script:testEnvironment + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force + + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} + +Describe 'DSC_xDhcpServerReservation\Get-TargetResource' -Tag 'Get' { + Context 'When the resource is present' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeID' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } + + Mock -CommandName Get-DhcpServerv4Scope + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPAddress' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.30' + } + + Mock -CommandName Get-DhcpServerv4Reservation -MockWith { + return @{ + ClientId = '00-15-5D-01-05-1B' + Name = Get-ComputerName + IPAddress = '192.168.1.30' + } + } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.1.0' + ClientMACAddress = '00-15-5D-01-05-1B' + IPAddress = '192.168.1.30' + AddressFamily = 'IPv4' + } + + $result = Get-TargetResource @testParams + + $result | Should -BeOfType [System.Collections.Hashtable] + $result.ScopeID | Should -Be $testParams.ScopeID + $result.IPAddress | Should -Be $testParams.IPAddress + $result.ClientMACAddress | Should -Be $testParams.ClientMACAddress + $result.Name | Should -Be (Get-ComputerName) + $result.AddressFamily | Should -Be $testParams.AddressFamily + $result.Ensure | Should -Be 'Present' + } + } + } + + Context 'When the resource is absent' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeID' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } + + Mock -CommandName Get-DhcpServerv4Scope + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPAddress' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.30' + } + + Mock -CommandName Get-DhcpServerv4Reservation + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.1.0' + ClientMACAddress = '00-15-5D-01-05-1B' + IPAddress = '192.168.1.30' + AddressFamily = 'IPv4' + } + + $result = Get-TargetResource @testParams + + $result | Should -BeOfType [System.Collections.Hashtable] + $result.ScopeID | Should -Be $testParams.ScopeID + $result.IPAddress | Should -Be $testParams.IPAddress + $result.ClientMACAddress | Should -BeNullOrEmpty + $result.Name | Should -BeNullOrEmpty + $result.AddressFamily | Should -Be $testParams.AddressFamily + $result.Ensure | Should -Be 'Absent' + } + } + } + + Context 'When the ScopeID is not valid' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeID' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } + + InModuleScope -ScriptBlock { + Mock -CommandName Get-DhcpServerv4Scope -MockWith { + Set-Variable -Name $PesterBoundParameters.ErrorVariable -Scope 3 -Value 'oh no' + } + } + } + + It 'Should throw the correct exception' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.1.0' + ClientMACAddress = '00-15-5D-01-05-1B' + IPAddress = '192.168.1.30' + AddressFamily = 'IPv4' + } + + $errorRecord = Get-InvalidOperationRecord -Message ($script:localizedData.InvalidScopeIdMessage -f $testParams.ScopeID) + + { Get-TargetResource @testParams } | Should -Throw -ExpectedMessage $errorRecord + } + } + } +} + +Describe 'DSC_xDhcpServerReservation\Set-TargetResource' -Tag 'Set' { + BeforeAll { + Mock -CommandName Update-ResourceProperties + } + + Context 'When supplying parameters that are removed' { + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.1.0' + ClientMACAddress = '00-15-5D-01-05-1B' + IPAddress = '192.168.1.10' + AddressFamily = 'IPv4' + Debug = $true + } + + Set-TargetResource @testParams + } + + Should -Invoke -CommandName Update-ResourceProperties -Exactly -Times 1 -Scope It + } + } +} + +Describe 'DSC_xDhcpServerReservation\Test-TargetResource' -Tag 'Test' { + Context 'When the resource is in the desired state' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeID' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } + + Mock -CommandName Get-DhcpServerv4Scope + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPAddress' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.30' + } + + Mock -CommandName Update-ResourceProperties -MockWith { + return $true + } + } + + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.1.0' + ClientMACAddress = '00-15-5D-01-05-1B' + IPAddress = '192.168.1.30' + AddressFamily = 'IPv4' + Ensure = 'Present' + Debug = $true + } + + Test-TargetResource @testParams + } + + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeID' + } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPAddress' + } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Update-ResourceProperties -Exactly -Times 1 -Scope It + } + } + + Context 'When the ScopeID is not valid' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeID' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } + + InModuleScope -ScriptBlock { + Mock -CommandName Get-DhcpServerv4Scope -MockWith { + Set-Variable -Name $PesterBoundParameters.ErrorVariable -Scope 3 -Value 'oh no' + } + } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.1.0' + ClientMACAddress = '00-15-5D-01-05-1B' + IPAddress = '192.168.1.30' + AddressFamily = 'IPv4' + } + + $errorRecord = Get-InvalidOperationRecord -Message ($script:localizedData.InvalidScopeIdMessage -f $testParams.ScopeID) + + { Test-TargetResource @testParams } | Should -Throw -ExpectedMessage $errorRecord + } + } + } +} + +Describe 'DSC_xDhcpServerReservation\Update-ResourceProperties' -Tag 'Helper' { + Context 'When a reservation exists' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Reservation -MockWith { + return @{ + ClientId = '00-15-5D-01-05-1B' + Name = Get-ComputerName + IPAddress = '192.168.30.10' + } + } + } + + Context 'When the parameter ''Apply'' is $false' { + Context 'When the resource is in the desired state' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Present' + } + + Update-ResourceProperties @testParams | Should -BeTrue + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource is not in the desired state' { + BeforeDiscovery { + $testCases = @( + @{ + Parameter = 'ClientMACAddress' + Value = '55155D01051B' + } + @{ + Parameter = 'Name' + Value = 'AnotherName' + } + ) + } + + Context 'When the '''' is different' -ForEach $testCases { + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Present' + } + + $testParams.$Parameter = $Value + + Update-ResourceProperties @testParams | Should -BeFalse + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource should be absent' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Absent' + } + + Update-ResourceProperties @testParams | Should -BeFalse + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + } + } + + Context 'When the parameter ''Apply'' is $true' { + Context 'When the resource is in the desired state' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Present' + Apply = $true + } + + Update-ResourceProperties @testParams + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource is not in the desired state' { + BeforeDiscovery { + $testCases = @( + @{ + Parameter = 'ClientMACAddress' + Value = '55155D01051B' + } + @{ + Parameter = 'Name' + Value = 'AnotherName' + } + ) + } + + Context 'When the '''' is different' -ForEach $testCases { + BeforeAll { + Mock -CommandName Set-DhcpServerv4Reservation + Mock -CommandName Write-PropertyMessage + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Present' + Apply = $true + } + + $testParams.$Parameter = $Value + + Update-ResourceProperties @testParams + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Write-PropertyMessage -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource should be removed' { + BeforeAll { + Mock -CommandName Remove-DhcpServerv4Reservation + } + + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Absent' + Apply = $true + } + + Update-ResourceProperties @testParams + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + } + } + } + + Context 'When a reservation does not exist' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Reservation + } + + Context 'When ''Apply'' is $false' { + Context 'When a reservation should exist' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Present' + } + + Update-ResourceProperties @testParams | Should -BeFalse + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + + Context 'When a reservation should not exist' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Absent' + } + + Update-ResourceProperties @testParams | Should -BeTrue + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + } + + Context 'When ''Apply'' is $true' { + Context 'When a reservation should exist' { + Context 'When the reservation is successfully created' { + BeforeAll { + Mock -CommandName Add-DhcpServerv4Reservation + } + + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Present' + Apply = $true + } + + Update-ResourceProperties @testParams + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + + Context 'When the reservation fails to be created' { + BeforeAll { + Mock -CommandName Add-DhcpServerv4Reservation -MockWith { throw } + } + + It 'Should throw and exception' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeID = '192.168.30.0' + ClientMACAddress = '00155D01051B' + IPAddress = '192.168.30.10' + Name = Get-ComputerName + AddressFamily = 'IPv4' + Ensure = 'Present' + Apply = $true + } + + { Update-ResourceProperties @testParams } | Should -Throw + } + + Should -Invoke -CommandName Get-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Reservation -Exactly -Times 1 -Scope It + } + } + } + } + } +} diff --git a/tests/Unit/DSC_xDhcpServerScope.Tests.ps1 b/tests/Unit/DSC_xDhcpServerScope.Tests.ps1 index da183b5..11939fe 100644 --- a/tests/Unit/DSC_xDhcpServerScope.Tests.ps1 +++ b/tests/Unit/DSC_xDhcpServerScope.Tests.ps1 @@ -1,16 +1,32 @@ -$script:dscModuleName = 'DhcpServerDsc' -$script:dscResourceName = 'DSC_xDhcpServerScope' +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () -function Invoke-TestSetup -{ +BeforeDiscovery { try { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } } catch [System.IO.FileNotFoundException] { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:dscResourceName = 'DSC_xDhcpServerScope' $script:testEnvironment = Initialize-TestEnvironment ` -DSCModuleName $script:dscModuleName ` @@ -18,114 +34,112 @@ function Invoke-TestSetup -ResourceType 'Mof' ` -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking -} + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName } -Invoke-TestSetup +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') -try -{ - InModuleScope $script:dscResourceName { - $testScopeName = 'Test Scope' - $testScopeID = '192.168.1.0' - $testIPStartRange = '192.168.1.10' - $testIPEndRange = '192.168.1.99' - $testSubnetMask = '255.255.255.0' - $testState = 'Active' - $testLeaseDuration = New-TimeSpan -Days 8 - $testDescription = 'Scope description' - $testAddressFamily = 'IPv4' - - $testParams = @{ - ScopeId = $testScopeID - Name = $testScopeName - IPStartRange = $testIPStartRange - IPEndRange = $testIPEndRange - SubnetMask = $testSubnetMask - Verbose = $true - } + Restore-TestEnvironment -TestEnvironment $script:testEnvironment - $fakeDhcpServerv4Scope = [PSCustomObject] @{ - ScopeID = $testScopeID - Name = $testScopeName - StartRange = $testIPStartRange - EndRange = $testIPEndRange - Description = $testDescription - SubnetMask = $testSubnetMask - LeaseDuration = $testLeaseDuration - State = $testState - AddressFamily = $testAddressFamily - } + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscResourceName -All | Remove-Module -Force - Describe 'DSC_xDhcpServerScope\Get-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module - } - - Mock -CommandName Assert-ScopeParameter -ParameterFilter { - $ScopeId -eq $testScopeID -and - $SubnetMask -eq $testSubnetMask -and - $IPStartRange -eq $testIPStartRange -and - $IPEndRange -eq $testIPEndRange -and - $AddressFamily -eq $testAddressFamily - } + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} - It 'Should call "Assert-Module" to ensure "DHCPServer" module is available' { - Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope - } +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } - { Get-TargetResource @testParams } | Should -Not -Throw + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { - $ModuleName -eq 'DHCPServer' - } -Exactly -Times 1 -Scope It - } + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/DhcpServer_2016_OSBuild_14393_2395.psm1" -Force -DisableNameChecking +} - It 'Should call "Assert-ScopeParameter" to ensure parameters passed are correct' { - Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope +Describe 'DSC_xDhcpServerScope\Get-TargetResource' -Tag 'Get' { + Context 'When the resource exists' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Assert-ScopeParameter + Mock -CommandName Get-DhcpServerv4Scope -MockWith { + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' } - - $result = Get-TargetResource @testParams - - Assert-MockCalled -CommandName Assert-Module -Exactly -Times 1 -Scope It } + } - It 'Should return a "System.Collections.Hashtable" object type' { - Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope - } - - Get-TargetResource @testParams | Should -BeOfType System.Collections.Hashtable - } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - It 'Should return all information about existing scope with specified ScopeId' { - Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' } $result = Get-TargetResource @testParams - $result.Name | Should -Be $testScopeName - $result.IPStartRange | Should -Be $testIPStartRange - $result.IPEndRange | Should -Be $testIPEndRange - $result.SubnetMask | Should -Be $testSubnetMask - $result.Description | Should -Be $testDescription - $result.LeaseDuration | Should -Be $testLeaseDuration - $result.State | Should -Be $testState - $result.AddressFamily | Should -Be $testAddressFamily + $result.Name | Should -Be $testParams.Name + $result.IPStartRange | Should -Be $testParams.IPStartRange + $result.IPEndRange | Should -Be $testParams.IPEndRange + $result.SubnetMask | Should -Be $testParams.SubnetMask + $result.Description | Should -Be 'Scope description' + $result.LeaseDuration | Should -Be (New-TimeSpan -Days 8) + $result.State | Should -Be 'Active' + $result.AddressFamily | Should -Be 'Ipv4' $result.Ensure | Should -Be Present } + } + } - It 'Should return basic information about missing scope with specified ScopeId' { - Mock -CommandName Get-DhcpServerv4Scope + Context 'When the resource does not exist' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Assert-ScopeParameter + Mock -CommandName Get-DhcpServerv4Scope + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + } $result = Get-TargetResource @testParams @@ -136,202 +150,689 @@ try $result.Description | Should -BeNullOrEmpty $result.LeaseDuration | Should -BeNullOrEmpty $result.State | Should -BeNullOrEmpty - $result.AddressFamily | Should -Be $testAddressFamily + $result.AddressFamily | Should -Be 'IPv4' $result.Ensure | Should -Be Absent } } + } +} - Describe 'DSC_xDhcpServerScope\Test-TargetResource' { - BeforeAll { - Mock -CommandName Assert-Module +Describe 'DSC_xDhcpServerScope\Test-TargetResource' -Tag 'Test' { + Context 'When the resource is in the desired state' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Assert-ScopeParameter + Mock -CommandName Update-ResourceProperties -MockWith { + return $true } + } - It 'Should return a "System.Boolean" object type' { - Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + AddressFamily = 'IPv4' + Debug = $true } - Test-TargetResource @testParams | Should -BeOfType System.Boolean + Test-TargetResource @testParams | Should -BeTrue } + } + } - It 'Should pass when all parameters are correct' { - Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + Context 'When the resource is not in the desired state' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Assert-ScopeParameter + Mock -CommandName Update-ResourceProperties -MockWith { + return $false + } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + AddressFamily = 'IPv4' + Debug = $true } - Test-TargetResource @testParams | Should -BeTrue + Test-TargetResource @testParams | Should -BeFalse } + } + } +} - It 'Should pass when optional parameter is correct' { - param - ( - [Parameter()] - $Parameter, +Describe 'DSC_xDhcpServerScope\Set-TargetResource' -Tag 'Set' { + Context 'When the resource should be updated' { + BeforeAll { + Mock -CommandName Assert-Module + Mock -CommandName Assert-ScopeParameter + Mock -CommandName Update-ResourceProperties + } - [Parameter()] - $Value - ) + It 'Should call the expected mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + AddressFamily = 'IPv4' + Debug = $true + } + Set-TargetResource @testParams + } + + Should -Invoke -CommandName Assert-Module -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Assert-ScopeParameter -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Update-ResourceProperties -Exactly -Times 1 -Scope It + } + } +} + +Describe 'DSC_xDhcpServerScope\Update-ResourceProperties' -Tag 'Helper' { + Context 'When testing DSC resource required properties' { + Context 'When the resource is present and correct' { + BeforeAll { Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $optionalParameters = @{ - $Parameter = $Value + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Apply = $false + } + + Update-ResourceProperties @testParams | Should -BeTrue } + } + } + + Context 'When the resource is absent and correct' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Scope + } - Test-TargetResource @testParams @optionalParameters | Should -BeTrue - } -TestCases @( - @{ - Parameter = 'Description' - Value = $testDescription + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Ensure = 'Absent' + Apply = $false + } + + Update-ResourceProperties @testParams | Should -BeTrue } - @{ - Parameter = 'LeaseDuration' - Value = $testLeaseDuration.ToString() + } + } + + Context 'When the resource is present and incorrect' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Scope -MockWith { + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } - @{ - Parameter = 'State' - Value = $testState + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Ensure = 'Absent' + Apply = $false + } + + Update-ResourceProperties @testParams | Should -BeFalse } - ) + } + } - It 'Should pass when "Ensure" = "Absent" and scope does not exist' { + Context 'When the resource is absent and incorrect' { + BeforeAll { Mock -CommandName Get-DhcpServerv4Scope - - Test-TargetResource @testParams -Ensure 'Absent' | Should -BeTrue } - It 'Should fail when parameter is incorrect' { - param - ( - [Parameter()] - $Parameter, + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Ensure = 'Present' + Apply = $false + } + + Update-ResourceProperties @testParams | Should -BeFalse + } + } + } - [Parameter()] - $Value + Context 'When an individual property is incorrect' { + BeforeDiscovery { + $testCases = @( + @{ + Parameter = 'Name' + Value = 'New Test Scope' + } + @{ + Parameter = 'IPStartRange' + Value = '192.168.1.20' + } + @{ + Parameter = 'IPEndRange' + Value = '192.168.1.199' + } + @{ + Parameter = 'SubnetMask' + Value = '255.255.254.0' + } ) + } + BeforeAll { Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } + } - $testNameParams = $testParams.Clone() - $testNameParams[$Parameter] = $Value + It 'Should return the correct result for property ''''' -ForEach $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 - Test-TargetResource @testNameParams | Should -BeFalse - } -TestCases @( - @{ - Parameter = 'Name' - Value = 'IncorrectName' - } - @{ - Parameter = 'IPStartRange' - Value = '192.168.1.1' - } - @{ - Parameter = 'IPEndRange' - Value = '192.168.1.254' - } - @{ - Parameter = 'SubnetMask' - Value = '255.255.255.128' + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Apply = $false + } + + $testParams.$Parameter = $Value + + Update-ResourceProperties @testParams | Should -BeFalse } - @{ - Parameter = 'Description' - Value = 'Wrong description' + } + } + } + + Context 'When testing DSC resource optional properties' { + Context 'When the resource is present and correct' { + BeforeDiscovery { + $testCases = @( + @{ + Parameter = 'Description' + Value = 'Scope description' + } + @{ + Parameter = 'LeaseDuration' + Value = New-TimeSpan -Days 8 + } + @{ + Parameter = 'State' + Value = 'Active' + } + ) + } + + BeforeAll { + Mock -CommandName Get-DhcpServerv4Scope -MockWith { + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } - @{ - Parameter = 'LeaseDuration' - Value = '08:00:00' + } + + It 'Should return the correct result for property ''''' -ForEach $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Apply = $false + $Parameter = $Value + } + + Update-ResourceProperties @testParams | Should -BeTrue } - @{ - Parameter = 'State' - Value = 'Inactive' + } + } + + Context 'When the resource is present and incorrect' { + BeforeDiscovery { + $testCases = @( + @{ + Parameter = 'Description' + Value = 'New Scope description' + } + @{ + Parameter = 'LeaseDuration' + Value = New-TimeSpan -Days 10 + } + @{ + Parameter = 'State' + Value = 'Inactive' + } + ) + } + + BeforeAll { + Mock -CommandName Get-DhcpServerv4Scope -MockWith { + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } - @{ - Parameter = 'Ensure' - Value = 'Absent' + } + + It 'Should return the correct result for property ''''' -ForEach $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Apply = $false + $Parameter = $Value + } + + Update-ResourceProperties @testParams | Should -BeFalse } - ) + } } + } - Describe 'DSC_xDhcpServerScope\Set-TargetResource' { + Context 'When setting the DSC resource with required properties' { + Context 'When the resource is present' { BeforeAll { - Mock -CommandName Assert-Module - } + Mock -CommandName Get-DhcpServerv4Scope -MockWith { + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } + } - It 'Should call "Add-DhcpServerv4Scope" when "Ensure" = "Present" and scope does not exist' { - Mock -CommandName Get-DhcpServerv4Scope Mock -CommandName Add-DhcpServerv4Scope + Mock -CommandName Remove-DhcpServerv4Scope + Mock -CommandName Set-DhcpServerv4Scope + } - Set-TargetResource @testParams + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Apply = $true + } + + Update-ResourceProperties @testParams + } - Assert-MockCalled -CommandName Add-DhcpServerv4Scope -ParameterFilter { - $StartRange -eq $testIPStartRange -and - $EndRange -eq $testIPEndRange -and - $SubnetMask -eq $testSubnetMask -and - $Name -eq $testScopeName - } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Scope -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Scope -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Scope -Exactly -Times 0 -Scope It + } + } + + Context 'When the resource is present and individual properties are incorrect' { + BeforeDiscovery { + $testCases = @( + @{ + Parameter = 'Name' + Value = 'New Test Scope' + AddCount = 0 + RemoveCount = 0 + SetCount = 1 + } + @{ + Parameter = 'IPStartRange' + Value = '192.168.1.20' + AddCount = 0 + RemoveCount = 0 + SetCount = 1 + } + @{ + Parameter = 'IPEndRange' + Value = '192.168.1.199' + AddCount = 0 + RemoveCount = 0 + SetCount = 1 + } + @{ + Parameter = 'SubnetMask' + Value = '255.255.254.0' + AddCount = 1 + RemoveCount = 1 + SetCount = 0 + } + @{ + Parameter = 'Description' + Value = 'New Scope description' + AddCount = 0 + RemoveCount = 0 + SetCount = 1 + } + @{ + Parameter = 'LeaseDuration' + Value = New-TimeSpan -Days 10 + AddCount = 0 + RemoveCount = 0 + SetCount = 1 + } + @{ + Parameter = 'State' + Value = 'Inactive' + AddCount = 0 + RemoveCount = 0 + SetCount = 1 + } + ) } - It 'Should call "Remove-DhcpServerv4Scope" when "Ensure" = "Absent" and scope does exist' { + BeforeAll { Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } + Mock -CommandName Add-DhcpServerv4Scope Mock -CommandName Remove-DhcpServerv4Scope + Mock -CommandName Set-DhcpServerv4Scope + } + + It 'Should call the correct mocks for property ''''' -ForEach $testCases { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Apply = $true + } - Set-TargetResource @testParams -Ensure 'Absent' + $testParams.$Parameter = $Value - Assert-MockCalled -CommandName Remove-DhcpServerv4Scope -ParameterFilter { - $ScopeId -eq $testScopeID - } -Exactly -Times 1 -Scope It + Update-ResourceProperties @testParams + } + + Should -Invoke -CommandName Get-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Scope -Exactly -Times $AddCount -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Scope -Exactly -Times $RemoveCount -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Scope -Exactly -Times $SetCount -Scope It } + } - It 'Should call "Set-DhcpServerv4Scope" when "Ensure" = "Present" and scope does exist' { + Context 'When the resource should be removed' { + BeforeAll { Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } + Mock -CommandName Add-DhcpServerv4Scope + Mock -CommandName Remove-DhcpServerv4Scope Mock -CommandName Set-DhcpServerv4Scope + } - Set-TargetResource @testParams -LeaseDuration '08:00:00' + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + Ensure = 'Absent' + Apply = $true + } + + Update-ResourceProperties @testParams + } - Assert-MockCalled -CommandName Set-DhcpServerv4Scope -ParameterFilter { - $ScopeId -eq $testScopeID -and - $LeaseDuration -eq (New-TimeSpan -Hours 8) - } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Scope -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Scope -Exactly -Times 0 -Scope It + } + } + + Context 'When the resource does not exist' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Scope + Mock -CommandName Add-DhcpServerv4Scope + Mock -CommandName Remove-DhcpServerv4Scope + Mock -CommandName Set-DhcpServerv4Scope } - It 'Should call "Remove-DhcpServerv4Scope" when "Ensure" = "Present", scope does exist but "SubnetMask" is incorrect' { + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + Apply = $true + } + + Update-ResourceProperties @testParams + } + + Should -Invoke -CommandName Get-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Scope -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Scope -Exactly -Times 0 -Scope It + } + } + + Context 'When updating the Subnet Mask fails' { + BeforeAll { Mock -CommandName Get-DhcpServerv4Scope -MockWith { - return $fakeDhcpServerv4Scope + return @{ + ScopeID = '192.168.1.0' + Name = 'Test Scope' + StartRange = '192.168.1.10' + EndRange = '192.168.1.99' + Description = 'Scope description' + SubnetMask = '255.255.255.0' + LeaseDuration = New-TimeSpan -Days 8 + State = 'Active' + AddressFamily = 'IPv4' + } } + Mock -CommandName Add-DhcpServerv4Scope + Mock -CommandName Remove-DhcpServerv4Scope -MockWith { throw } + Mock -CommandName Set-DhcpServerv4Scope + } + + It 'Should throw the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.254.0' + Apply = $true + } + + { Update-ResourceProperties @testParams } | Should -Throw + } + + Should -Invoke -CommandName Get-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Scope -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Scope -Exactly -Times 0 -Scope It + } + + } + + Context 'When creating the resource fails' { + BeforeAll { + Mock -CommandName Get-DhcpServerv4Scope + Mock -CommandName Add-DhcpServerv4Scope -MockWith { throw } Mock -CommandName Remove-DhcpServerv4Scope Mock -CommandName Set-DhcpServerv4Scope + } - $testSubnetMaskParams = $testParams.Clone() - $testSubnetMaskParams['SubnetMask'] = '255.255.255.128' + It 'Should throw the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Set-TargetResource @testSubnetMaskParams + $testParams = @{ + ScopeId = '192.168.1.0' + Name = 'Test Scope' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.254.0' + Apply = $true + } - Assert-MockCalled -CommandName Remove-DhcpServerv4Scope -ParameterFilter { - $ScopeId -eq $testScopeID - } -Exactly -Times 1 -Scope It + { Update-ResourceProperties @testParams } | Should -Throw + } - Assert-MockCalled -CommandName Add-DhcpServerv4Scope -ParameterFilter { - $StartRange -eq $testIPStartRange -and - $EndRange -eq $testIPEndRange -and - $SubnetMask -eq '255.255.255.128' -and - $Name -eq $testScopeName - } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Add-DhcpServerv4Scope -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Remove-DhcpServerv4Scope -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Set-DhcpServerv4Scope -Exactly -Times 0 -Scope It } + } } } -finally -{ - Invoke-TestCleanup -} diff --git a/tests/Unit/DhcpServerDsc.Common.Tests.ps1 b/tests/Unit/DhcpServerDsc.Common.Tests.ps1 index 8c5f8f3..6be1b23 100644 --- a/tests/Unit/DhcpServerDsc.Common.Tests.ps1 +++ b/tests/Unit/DhcpServerDsc.Common.Tests.ps1 @@ -1,98 +1,513 @@ -#region HEADER +<# + .SYNOPSIS + Unit test for DhcpServerDsc Common. +#> -$script:projectPath = "$PSScriptRoot\..\.." | Convert-Path -$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { - ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and - $(try +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) { - Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null } - catch - { - $false - }) - }).BaseName -$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 -$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' -Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:subModuleName = 'DhcpServerDsc.Common' + + $script:parentModule = Get-Module -Name $script:dscModuleName -ListAvailable | Select-Object -First 1 + $script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' + + $script:subModulePath = Join-Path -Path $script:subModulesFolder -ChildPath $script:subModuleName -$script:subModuleName = (Split-Path -Path $PSCommandPath -Leaf) -replace '\.Tests.ps1' -$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" + Import-Module -Name $script:subModulePath -Force -ErrorAction 'Stop' -Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' -#endregion HEADER + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:subModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:subModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:subModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:subModuleName -All | Remove-Module -Force +} -InModuleScope $script:subModuleName { - $testParams = @{ - ScopeId = '192.168.1.0' - IPStartRange = '192.168.1.10' - IPEndRange = '192.168.1.99' - SubnetMask = '255.255.255.0' - AddressFamily = 'IPv4' - Verbose = $true +Describe 'DhcpServerDsc.Common\New-TerminatingError' { + It 'Should throw a terminating error with the specified message' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + ErrorId = 'TestErrorId' + ErrorMessage = 'Test message' + ErrorCategory = 'InvalidType' + } + + { New-TerminatingError @testParameters } | Should -Throw -ExpectedMessage $testParameters.ErrorMessage + } } +} + +Describe 'DhcpServerDsc.Common\Get-ValidIPAddress' { + Context 'When getting a valid IPv4 Address' { + Context 'When the ''AddressFamily'' matches' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - Describe 'DhcpServerDsc.Common\Assert-ScopeParameter' { - It 'Should not throw when parameters are correct' { - { Assert-ScopeParameter @testParams } | Should -Not -Throw + $testParameters = @{ + IpString = '255.255.255.0' + AddressFamily = 'IPv4' + ParameterName = 'SubnetMask' + } + + $result = Get-ValidIPAddress @testParameters + + $result | Should -BeOfType [System.Net.IPAddress] + $result | Should -Be $testParameters.IpString + $result.AddressFamily | Should -Be 'InterNetwork' + } + } + } + + Context 'When the ''AddressFamily'' does not match' { + BeforeAll { + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -MockWith { throw } + + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -MockWith { throw } + } + + It 'Should return the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + IpString = '255.255.255.0' + AddressFamily = 'IPv6' + ParameterName = 'SubnetMask' + } + + { Get-ValidIPAddress @testParameters } | Should -Throw + } + + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -Exactly -Times 0 -Scope It + + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -Exactly -Times 1 -Scope It + } } + } - It 'Should return nothing when parameters are correct' { - Assert-ScopeParameter @testParams | Should -BeNullOrEmpty + Context 'When getting an invalid IPv4 Address' { + BeforeAll { + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -MockWith { throw } + + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -MockWith { throw } } - It 'Should throw an exception with ErrorId and information about incorrect ()' { - param - ( - [Parameter()] - [System.String] - $Parameter, + It 'Should return the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + IpString = '255.255.255.x' + AddressFamily = 'IPv4' + ParameterName = 'SubnetMask' + } + + { Get-ValidIPAddress @testParameters } | Should -Throw + } - [Parameter()] - [System.String] - $Value, + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -Exactly -Times 1 -Scope It - [Parameter()] - [System.String] - $ErrorPattern, + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -Exactly -Times 0 -Scope It + } + } + + Context 'When getting a valid IPv6 Address' { + Context 'When the ''AddressFamily'' matches' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + IpString = '2001:0db8:85a3:1234:1234:8a2e:0370:7334' + AddressFamily = 'IPv6' + ParameterName = 'SubnetMask' + } + + $result = Get-ValidIPAddress @testParameters + + $result | Should -BeOfType [System.Net.IPAddress] + $result | Should -Be '2001:db8:85a3:1234:1234:8a2e:370:7334' + $result.AddressFamily | Should -Be 'InterNetworkV6' + } + } + } + + Context 'When the ''AddressFamily'' does not match' { + BeforeAll { + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -MockWith { throw } + + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -MockWith { throw } + } + + It 'Should return the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + IpString = '2001:0db8:85a3:1234:1234:8a2e:0370:7334' + AddressFamily = 'IPv4' + ParameterName = 'SubnetMask' + } + + { Get-ValidIPAddress @testParameters } | Should -Throw + } + + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -Exactly -Times 0 -Scope It + + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -Exactly -Times 1 -Scope It + } + } + } + + Context 'When getting an invalid IPv6 Address' { + BeforeAll { + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -MockWith { throw } + + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -MockWith { throw } + } + + It 'Should return the correct error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + IpString = '255.255.255.x' + AddressFamily = 'IPv6' + ParameterName = 'SubnetMask' + } + + { Get-ValidIPAddress @testParameters } | Should -Throw + } + + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidIPAddress' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'InvalidIPAddressFamily' + } -Exactly -Times 0 -Scope It + } + } +} + +Describe 'DhcpServerDsc.Common\Assert-ScopeParameter' { + Context 'When parameters are correct' { + BeforeAll { + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'SubnetMask' + } -MockWith { + return [System.Net.IPAddress] '255.255.255.0' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeId' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } - [Parameter()] - [System.String] - $ErrorId + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPStartRange' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.10' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPEndRange' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.99' + } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + AddressFamily = 'IPv4' + } + + $result = Assert-ScopeParameter @testParams + + { $result } | Should -Not -Throw + $result | Should -BeNullOrEmpty + } + + Should -Invoke -CommandName Get-ValidIPAddress -Exactly -Times 4 -Scope It + } + } + + Context 'When start or end range is not correct' { + BeforeAll { + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'SubnetMask' + } -MockWith { + return [System.Net.IPAddress] '255.255.255.0' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeId' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPStartRange' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.100' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPEndRange' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.99' + } + + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'RangeNotCorrect' + } -MockWith { throw } + } + + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + IPStartRange = '192.168.1.100' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + AddressFamily = 'IPv4' + } + + { Assert-ScopeParameter @testParams } | Should -Throw + } + + Should -Invoke -CommandName Get-ValidIPAddress -Exactly -Times 4 -Scope It + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'RangeNotCorrect' + } -Exactly -Times 1 -Scope It + } + } + + Context 'When Parameters parameter are incorrect' { + BeforeDiscovery { + $testCases = @( + @{ + Parameter = 'ScopeId' + Value = '192.168.1.42' + ErrorId = 'ScopeIdOrMaskIncorrect' + } + @{ + Parameter = 'IPStartRange' + Value = '192.168.0.1' + ErrorId = 'ScopeIdOrMaskIncorrect' + } + @{ + Parameter = 'IPEndRange' + Value = '192.167.1.100' + ErrorId = 'ScopeIdOrMaskIncorrect' + } ) + } + + Context 'When '''' is incorrect' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'SubnetMask' + } -MockWith { + return [System.Net.IPAddress] '255.255.255.0' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'ScopeId' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.0' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPStartRange' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.10' + } + + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq 'IPEndRange' + } -MockWith { + return [System.Net.IPAddress] '192.168.1.99' + } - $brokenTestParams = $testParams.Clone() - $brokenTestParams[$Parameter] = $Value - - { Assert-ScopeParameter @brokenTestParams } | Should -Throw -ExpectedMessage $ErrorPattern -ErrorId $ErrorId - } -TestCases @( - #TODO: Removed to get the pipeline working, need to fix this test so iyt does not fail. It gives different result on macOS and in the pipeline (both using PS7). - # @{ - # Parameter = 'ScopeId' - # Value = '192.168.1.42' - # ErrorPattern = 'Value of byte 4 in ScopeId (42) is not valid.' - # ErrorId = 'ScopeIdOrMaskIncorrect' - # } - @{ - Parameter = 'IPStartRange' - Value = '192.168.0.1' - ErrorPattern = 'Value of byte 3 in IPStartRange (0) is not valid.' - ErrorId = 'ScopeIdOrMaskIncorrect' - } - @{ - Parameter = 'IPEndRange' - Value = '192.167.1.100' - ErrorPattern = 'Value of byte 2 in IPEndRange (167) is not valid.' - ErrorId = 'ScopeIdOrMaskIncorrect' - } - @{ - Parameter = 'IPEndRange' - Value = '192.168.1.2' - ErrorPattern = 'not valid. Start should be lower than end.' - ErrorId = 'RangeNotCorrect' - } - ) + # Override the correct mock + Mock -CommandName Get-ValidIPAddress -ParameterFilter { + $ParameterName -eq $Parameter + } -MockWith { + return [System.Net.IPAddress] $Value + } + + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq $ErrorId + } -MockWith { throw } + } + + It 'Should throw an exception with ErrorId and information about incorrect ()' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + ScopeId = '192.168.1.0' + IPStartRange = '192.168.1.10' + IPEndRange = '192.168.1.99' + SubnetMask = '255.255.255.0' + AddressFamily = 'IPv4' + Verbose = $true + } + + $testParams.$Parameter = $Value + + { Assert-ScopeParameter @testParams } | Should -Throw + } + + Should -Invoke -CommandName Get-ValidIPAddress -Exactly -Times 4 -Scope It + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq $ErrorId + } -Exactly -Times 1 -Scope It + } + } + } +} + +Describe 'DhcpServerDsc.Common\Write-PropertyMessage' { + Context 'When no keys need to be skipped' { + BeforeAll { + Mock -CommandName Write-Verbose + } + + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams = @{ + Parameters = @{ + PropertyName = 'TestProperty' + PropertyValue = 'TestValue' + } + KeysToSkip = @('Somekey') + MessageTemplate = 'Mock message template {0}' + } + + Write-PropertyMessage @testParams + } + + Should -Invoke -CommandName Write-Verbose -Exactly -Times 2 -Scope It + } + } +} + +Describe 'DhcpServerDsc.Common\Get-ValidTimeSpan' { + Context 'When the TimeSpan string is valid' { + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + TsString = '00:00:00' + ParameterName = 'LeaseDuration' + } + + $result = Get-ValidTimeSpan @testParameters + + $result | Should -BeOfType [System.TimeSpan] + $result | Should -Be '00:00:00' + } + } + } + + Context 'When the TimeSpan string is not valid' { + BeforeAll { + Mock -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidTimeSpan' + } -MockWith { throw } + } + It 'Should return the correct result' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParameters = @{ + TsString = '00:00:00?' + ParameterName = 'LeaseDuration' + } + + { Get-ValidTimeSpan @testParameters } | Should -Throw + } + + Should -Invoke -CommandName New-TerminatingError -ParameterFilter { + $ErrorId -eq 'NotValidTimeSpan' + } -Exactly -Times 1 -Scope It + } } } diff --git a/tests/Unit/DhcpServerDsc.OptionValueHelper.Tests.ps1 b/tests/Unit/DhcpServerDsc.OptionValueHelper.Tests.ps1 new file mode 100644 index 0000000..22cba10 --- /dev/null +++ b/tests/Unit/DhcpServerDsc.OptionValueHelper.Tests.ps1 @@ -0,0 +1,492 @@ +<# + .SYNOPSIS + Unit test for DhcpServerDsc OptionValueHelper. +#> + +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'DhcpServerDsc' + $script:subModuleName = 'DhcpServerDsc.OptionValueHelper' + + $script:parentModule = Get-Module -Name $script:dscModuleName -ListAvailable | Select-Object -First 1 + $script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' + + $script:subModulePath = Join-Path -Path $script:subModulesFolder -ChildPath $script:subModuleName + + Import-Module -Name $script:subModulePath -Force -ErrorAction 'Stop' + + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\DhcpServer_2016_OSBuild_14393_2395.psm1') -DisableNameChecking + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:subModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:subModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:subModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:subModuleName -All | Remove-Module -Force + + Remove-Module -Name 'DhcpServer_2016_OSBuild_14393_2395' -Force +} + +Describe 'DhcpServerDsc.OptionValueHelper\Get-TargetResourceHelper' { + BeforeDiscovery { + $testCases = @( + @{ + testParams = @{ + ApplyTo = 'Server' + OptionId = 1 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + } + + mockResult = @{ + OptionId = 1 + } + } + @{ + testParams = @{ + ApplyTo = 'Scope' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.10.0' + AddressFamily = 'IPv4' + } + + mockResult = @{ + OptionId = 1 + } + } + @{ + testParams = @{ + ApplyTo = 'Policy' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.10.0' + AddressFamily = 'IPv4' + } + + mockResult = @{ + OptionId = 1 + } + } + @{ + testParams = @{ + ApplyTo = 'Policy' + OptionId = 1 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + } + + mockResult = @{ + OptionId = 1 + } + } + @{ + testParams = @{ + ApplyTo = 'ReservedIP' + OptionId = 1 + VendorClass = '' + UserClass = '' + ReservedIP = '192.168.10.0' + AddressFamily = 'IPv4' + } + + mockResult = @{ + OptionId = 1 + } + } + ) + } + + BeforeAll { + Mock -CommandName Assert-Module + } + + Context 'When the the DhcpOption Exists' { + Context 'When ApplyTo is ''''' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-DhcpServerv4OptionValue -MockWith { + $mockResult + } + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $result = Get-TargetResourceHelper @testParams + + $result.Ensure | Should -Be 'Present' + $result.AddressFamily | Should -Be 'IPv4' + } + + Should -Invoke -CommandName Get-DhcpServerv4OptionValue -Exactly -Times 1 -Scope It + } + } + } + + Context 'When the the DhcpOption does not exist' { + Context 'When ApplyTo is ''''' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-DhcpServerv4OptionValue + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $result = Get-TargetResourceHelper @testParams + + $result.Ensure | Should -Be 'Absent' + $result.AddressFamily | Should -BeNullOrEmpty + } + + Should -Invoke -CommandName Get-DhcpServerv4OptionValue -Exactly -Times 1 -Scope It + } + } + } +} + +Describe 'DhcpServerDsc.OptionValueHelper\Test-TargetResourceHelper' { + BeforeDiscovery { + $testCases = @( + @{ + testParams = @{ + ApplyTo = 'Server' + OptionId = 1 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + } + } + @{ + testParams = @{ + ApplyTo = 'Scope' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.0.1' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + } + } + @{ + testParams = @{ + ApplyTo = 'Policy' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.0.1' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + } + } + @{ + testParams = @{ + ApplyTo = 'ReservedIP' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.0.1' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + } + } + ) + } + + Context 'When the DhcpOption should exist and does for ' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -MockWith { + $mockResult + } + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockResult.Ensure = 'Present' + + $result = Test-TargetResourceHelper @testParams + + $result | Should -BeTrue + } + + Should -Invoke -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -Exactly -Times 1 -Scope It + } + } + + Context 'When the DhcpOption should exist and does not for ' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -MockWith { + @{ + Ensure = 'Absent' + } + } + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $result = Test-TargetResourceHelper @testParams + + $result | Should -BeFalse + } + + Should -Invoke -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -Exactly -Times 1 -Scope It + } + } + + Context 'When the DhcpOption should not exist and does for ' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -MockWith { + $mockResult + } + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams.Ensure = 'Absent' + $mockResult.Ensure = 'Present' + + $result = Test-TargetResourceHelper @testParams + + $result | Should -BeFalse + } + + Should -Invoke -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -Exactly -Times 1 -Scope It + } + } + + Context 'When the DhcpOption should not exist and does for ' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -MockWith { + @{ + Ensure = 'Absent' + } + } + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams.Ensure = 'Absent' + + $result = Test-TargetResourceHelper @testParams + + $result | Should -BeTrue + } + + Should -Invoke -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -Exactly -Times 1 -Scope It + } + } +} + +Describe 'DhcpServerDsc.OptionValueHelper\Set-TargetResourceHelper' { + BeforeDiscovery { + $testCases = @( + @{ + testParams = @{ + ApplyTo = 'Server' + OptionId = 1 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + } + } + @{ + testParams = @{ + ApplyTo = 'Scope' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.0.1' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + OptionId = 1 + } + } + @{ + testParams = @{ + ApplyTo = 'Policy' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.0.1' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + } + } + @{ + testParams = @{ + ApplyTo = 'Policy' + OptionId = 1 + VendorClass = '' + UserClass = '' + AddressFamily = 'IPv4' + Value = '10' + } + + mockResult = @{ + Value = '10' + } + } + @{ + testParams = @{ + ApplyTo = 'ReservedIP' + OptionId = 1 + VendorClass = '' + UserClass = '' + ScopeId = '192.168.0.1' + AddressFamily = 'IPv4' + Value = '10' + ReservedIP = '10.0.0.100' + } + + mockResult = @{} + } + ) + } + + Context 'When the DhcpOption should exist for ' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -MockWith { + $mockResult + } + + Mock -CommandName Set-DhcpServerv4OptionValue + } + + It 'Should call the correct mocks' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockResult.Ensure = 'Present' + + $result = Set-TargetResourceHelper @testParams + } + + Should -Invoke -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Set-DhcpServerv4OptionValue -Exactly -Times 1 -Scope It + } + } + + Context 'When the DhcpOption should not exist for ' -ForEach $testCases { + BeforeAll { + Mock -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -MockWith { + $mockResult + } + + Mock -CommandName Remove-DhcpServerv4OptionValue + } + + It 'Should return the correct result' { + InModuleScope -Parameters $_ -ScriptBlock { + Set-StrictMode -Version 1.0 + + $testParams.Ensure = 'Absent' + $mockResult.Ensure = 'Present' + + $result = Set-TargetResourceHelper @testParams + } + + Should -Invoke -CommandName Get-TargetResourceHelper -ParameterFilter { + $ApplyTo -eq $testParams.ApplyTo + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Remove-DhcpServerv4OptionValue -Exactly -Times 1 -Scope It + } + } +}