Tests/.Unit/MSFT_UpdateServicesServer.tests.ps1
<#
.Synopsis Unit tests for UpdateServicesServer .DESCRIPTION Unit tests for UpdateServicesServer .NOTES Code in HEADER and FOOTER regions are standard and may be moved into DSCResource.Tools in Future and therefore should not be altered if possible. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '',Scope='Function',Target='DSCGetValues')] param() $Global:DSCModuleName = 'UpdateServicesDsc' # Example xNetworking $Global:DSCResourceName = 'MSFT_UpdateServicesServer' # Example MSFT_xFirewall #region HEADER [String] $moduleRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $Script:MyInvocation.MyCommand.Path)) if ( (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` (-not (Test-Path -Path (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) { & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\')) } else { & git @('-C',(Join-Path -Path $moduleRoot -ChildPath '\DSCResource.Tests\'),'pull') } Import-Module (Join-Path -Path $moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force $TestEnvironment = Initialize-TestEnvironment ` -DSCModuleName $Global:DSCModuleName ` -DSCResourceName $Global:DSCResourceName ` -TestType Unit #endregion # Begin Testing try { #region Pester Tests # The InModuleScope command allows you to perform white-box unit testing on the internal # (non-exported) code of a Script Module. InModuleScope $Global:DSCResourceName { #region Pester Test Initialization Import-Module $PSScriptRoot\..\..\Tests\Helpers\ImitateUpdateServicesModule.psm1 -force $DSCGetValues = @{ SQLServer = 'SQLServer' ContentDir = 'C:\WSUSContent\' UpdateImprovementProgram = $true UpstreamServerName = '' UpstreamServerPort = $null UpstreamServerSSL = $null UpstreamServerReplica = $null ProxyServerName = '' ProxyServerPort = $null ProxyServerCredentialUsername = $null ProxyServerBasicAuthentication = $null Languages = '*' Products = '*' Classifications = '*' SynchronizeAutomatically = $true SynchronizeAutomaticallyTimeOfDay = '04:00:00' SynchronizationsPerDay = 24 } $DSCTestValues = @{ SetupCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist 'foo', $('bar' | ConvertTo-SecureString -AsPlainText -Force) SQLServer = 'SQLServer' ContentDir = 'C:\WSUSContent\' UpdateImprovementProgram = $true UpstreamServerName = 'UpstreamServer' UpstreamServerPort = $false UpstreamServerSSL = $false UpstreamServerReplica = $false ProxyServerName = 'ProxyServer' ProxyServerPort = 8080 Languages = "*" Products = @("Windows","Office") Classifications = @('E6CF1350-C01B-414D-A61F-263D14D133B4','E0789628-CE08-4437-BE74-2495B842F43B','0FA1201D-4330-4FA8-8AE9-B877473B6441') SynchronizeAutomatically = $true SynchronizeAutomaticallyTimeOfDay = '04:00:00' SynchronizationsPerDay = 24 } #endregion #region Function Get-TargetResource expecting Ensure Present Describe "$($Global:DSCResourceName)\Get-TargetResource" { Mock -CommandName Get-ItemProperty -ParameterFilter {$Path -eq 'HKLM:\SOFTWARE\Microsoft\Update Services\Server\Setup' -and $Name -eq 'SQLServerName'} -MockWith {@{SQLServerName = 'SQLServer'}} -Verifiable Mock -CommandName Get-ItemProperty -ParameterFilter {$Path -eq 'HKLM:\SOFTWARE\Microsoft\Update Services\Server\Setup' -and $Name -eq 'ContentDir'} -MockWith {@{ContentDir = 'C:\WSUSContent\'}} -Verifiable Context 'server should be configured.' { it 'calling Get should not throw' { {$Script:resource = Get-TargetResource -Ensure 'Present' -verbose} | should not throw } it 'sets the value for Ensure' { $Script:resource.Ensure | should be 'Present' } foreach ($setting in $DSCSetValues.Keys) { it "returns $setting in Get results" { $Script:resource.$setting | should be $DSCGetReturnValues.$setting } } it 'mocks were called' { Assert-VerifiableMock } } Context 'server should not be configured.' { it 'calling Get should not throw' { Mock -CommandName Get-WSUSServer -MockWith {} {$Script:resource = Get-TargetResource -Ensure 'Absent' -verbose} | should not throw } it 'sets the value for Ensure' { $Script:resource.Ensure | should be 'Absent' } it 'mocks were called' { Assert-VerifiableMock } } } #endregion #region Function Test-TargetResource Describe "$($Global:DSCResourceName)\Test-TargetResource" { Context 'server is in correct state (Ensure=Present)' { $DSCTestValues.Remove('Ensure') $DSCTestValues.Add('Ensure','Present') Mock -CommandName Get-TargetResource -MockWith {$DSCTestValues} -Verifiable $script:result = $null it 'calling test should not throw' { {$script:result = Test-TargetResource @DSCTestValues -verbose} | should not throw } it "result should be true" { $script:result | should be $true } it 'mocks were called' { Assert-VerifiableMock } } Context 'server should not be configured (Ensure=Absent)' { $DSCTestValues.Remove('Ensure') $DSCTestValues.Add('Ensure','Absent') Mock -CommandName Get-TargetResource -MockWith {$DSCTestValues} -Verifiable $script:result = $null it 'calling test should not throw' { {$script:result = Test-TargetResource @DSCTestValues -verbose} | should not throw } it "result should be true" { $script:result | should be $true } it 'mocks were called' { Assert-VerifiableMock } } Context 'server should be configured correctly but is not' { $DSCTestValues.Remove('Ensure') Mock -CommandName Get-TargetResource -MockWith {$DSCTestValues} -Verifiable $script:result = $null it 'calling test should not throw' { {$script:result = Test-TargetResource @DSCTestValues -Ensure 'Present' -verbose} | should not throw } it "result should be false" { $script:result | should be $false } it 'mocks were called' { Assert-VerifiableMock } } Context "setting has drifted" { $DSCTestValues.Remove('Ensure') $DSCTestValues.Add('Ensure','Present') # Settings not currently tested: ProxyServerUserName, ProxyServerCredential, ProxyServerBasicAuthentication, 'Languages', 'Products', 'Classifications', 'SynchronizeAutomatically' $settingsList = 'UpdateImprovementProgram', 'UpstreamServerName', 'UpstreamServerPort', 'UpstreamServerSSL', 'UpstreamServerReplica', 'ProxyServerName', 'ProxyServerPort', 'SynchronizeAutomaticallyTimeOfDay', 'SynchronizationsPerDay' foreach ($setting in $settingsList) { Mock -CommandName Get-TargetResource -MockWith { $DSCTestValues.Remove("$setting") $DSCTestValues } -Verifiable $script:result = $null it "calling test with change to $setting should not throw" { {$script:result = Test-TargetResource @DSCTestValues -verbose} | should not throw } it "result should be false when $setting has changed" { $script:result | should be $false } it 'mocks were called' { Assert-VerifiableMock } $DSCTestValues.Add("$setting",$true) } } } #endregion #region Function Set-TargetResource Describe "$($Global:DSCResourceName)\Set-TargetResource" { $DSCTestValues.Remove('Ensure') Mock -CommandName Test-TargetResource -MockWith {$true} Mock -CommandName New-TerminatingError -MockWith {} Mock SaveWsusConfiguration -MockWith {} Context 'resource is idempotent (Ensure=Present)' { it 'should not throw when running on a properly configured server' { {Set-targetResource @DSCTestValues -Ensure Present -verbose} | should not throw } it "mocks were called" { Assert-MockCalled -CommandName Test-TargetResource -Times 1 Assert-MockCalled -CommandName SaveWsusConfiguration -Times 1 } it "mocks were not called that log errors" { Assert-MockCalled -CommandName New-TerminatingError -Times 0 } } Context 'resource supports Ensure=Absent' { it 'should not throw when running on a properly configured server' { {Set-targetResource @DSCTestValues -Ensure Absent -verbose} | should not throw } it "mocks were called" { Assert-MockCalled -CommandName Test-TargetResource -Times 1 Assert-MockCalled -CommandName SaveWsusConfiguration -Times 1 } it "mocks were not called that log errors" { Assert-MockCalled -CommandName New-TerminatingError -Times 0 } } } #endregion } } finally { #region FOOTER Restore-TestEnvironment -TestEnvironment $TestEnvironment #endregion } |