From 21c49fb99b86fb8cdd1f66d152833413793cbf58 Mon Sep 17 00:00:00 2001 From: NicolasBN Date: Fri, 9 Sep 2022 13:51:38 +0200 Subject: [PATCH 1/3] Updated pester test to support pester v5 --- CHANGELOG.md | 1 + RequiredModules.psd1 | 2 +- .../MSFT_UpdateServicesApprovalRule.tests.ps1 | 272 +++++++------ .../Unit/MSFT_UpdateServicesCleanup.tests.ps1 | 363 ++++++++++-------- .../Unit/MSFT_UpdateServicesServer.tests.ps1 | 295 +++++++------- build.yaml | 66 ++-- 6 files changed, 528 insertions(+), 471 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d12687..2d6445f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 of pipeline artifact - Updated build.ps1 script and build.yaml. - Changed default timeout in Wait-Win32ProcessStart function for cab installation. +- Updated pester test to support pester v5 ### Added diff --git a/RequiredModules.psd1 b/RequiredModules.psd1 index a75b081..0945827 100644 --- a/RequiredModules.psd1 +++ b/RequiredModules.psd1 @@ -11,7 +11,7 @@ 'powershell-yaml' = 'latest' InvokeBuild = 'latest' PSScriptAnalyzer = 'latest' - Pester = '4.10.1' + Pester = '5.3.3' Plaster = 'latest' ModuleBuilder = '1.0.0' ChangelogManagement = 'latest' diff --git a/Tests/Unit/MSFT_UpdateServicesApprovalRule.tests.ps1 b/Tests/Unit/MSFT_UpdateServicesApprovalRule.tests.ps1 index 848bf1c..7cbc442 100644 --- a/Tests/Unit/MSFT_UpdateServicesApprovalRule.tests.ps1 +++ b/Tests/Unit/MSFT_UpdateServicesApprovalRule.tests.ps1 @@ -12,6 +12,10 @@ $TestEnvironment = Initialize-TestEnvironment ` -ResourceType 'Mof' ` -TestType Unit +#region Pester Test Initialization +Import-Module $PSScriptRoot\..\Helpers\ImitateUpdateServicesModule.psm1 -force -ErrorAction Stop +#Import-Module (Join-Path -Path $PSScriptRoot -ChildPath '..\..\source\Modules\PDT\PDT.psm1') -force -ErrorAction Stop + #endregion HEADER @@ -19,62 +23,61 @@ $TestEnvironment = Initialize-TestEnvironment ` try { InModuleScope $script:DSCResourceName { + BeforeAll { + $script:WsusServer = [pscustomobject]@{ + Name = 'ServerName' + } - #region Pester Test Initialization - Import-Module $PSScriptRoot\..\Helpers\ImitateUpdateServicesModule.psm1 - - $global:WsusServer = [pscustomobject] @{Name = 'ServerName'} - - $DSCSetValues = - @{ - Name = $Global:WsusServer.Name - Classifications = "00000000-0000-0000-0000-0000testguid" - Products = "Product" - ComputerGroups = "Computer Target Group" - Enabled = $true - } + $DSCSetValues = @{ + Name = $script:WsusServer.Name + Classifications = "00000000-0000-0000-0000-0000testguid" + Products = "Product" + ComputerGroups = "Computer Target Group" + Enabled = $true + } - $DSCTestValues = - @{ - Name = $Global:WsusServer.Name + $DSCTestValues = @{ + Name = $script:WsusServer.Name Classifications = "00000000-0000-0000-0000-0000testguid" Products = "Product" ComputerGroups = "Computer Target Group" Enabled = $true + } } #endregion #region Function Get-TargetResource expecting Ensure Present Describe "MSFT_UpdateServicesApprovalRule\Get-TargetResource" { - - Mock -CommandName New-InvalidOperationException -MockWith {} - Mock -CommandName New-InvalidResultException -MockWith {} - Mock -CommandName New-InvalidArgumentException -MockWith {} + BeforeAll { + Mock -CommandName New-InvalidOperationException -MockWith {} + Mock -CommandName New-InvalidResultException -MockWith {} + Mock -CommandName New-InvalidArgumentException -MockWith {} + } Context 'server should be configured.' { it 'calling Get should not throw' { - {$Script:resource = Get-TargetResource -Name $Global:WsusServer.Name -verbose} | should not throw + {$Script:resource = Get-TargetResource -Name $script:WsusServer.Name -verbose} | should -not -throw } it "Ensure" { - $Script:resource.Ensure | should be 'Present' + $Script:resource.Ensure | should -Be 'Present' } it "Classifications" { - $Script:resource.Classifications | should be $DSCSetValues.Classifications + $Script:resource.Classifications | should -Be $DSCSetValues.Classifications } it "Products" { - $Script:resource.Products | should be $DSCSetValues.Products + $Script:resource.Products | should -Be $DSCSetValues.Products } it "Computer Groups" { - $Script:resource.ComputerGroups | should be $DSCSetValues.ComputerGroups + $Script:resource.ComputerGroups | should -Be $DSCSetValues.ComputerGroups } it "Enabled" { - $Script:resource.Enabled | should be $DSCSetValues.Enabled + $Script:resource.Enabled | should -Be $DSCSetValues.Enabled } it "mocks were not called" { @@ -89,27 +92,27 @@ try it 'calling Get should not throw' { Mock -CommandName Get-WSUSServer -MockWith {} -Verifiable - {$Script:resource = Get-TargetResource -Name $Global:WsusServer.Name -verbose} | should not throw + {$Script:resource = Get-TargetResource -Name $script:WsusServer.Name -verbose} | should -not -throw } it "Ensure" { - $Script:resource.Ensure | should be 'Absent' + $Script:resource.Ensure | should -Be 'Absent' } it "Classifications" { - $Script:resource.Classifications | should BeNullOrEmpty + $Script:resource.Classifications | should -BeNullOrEmpty } it "Products" { - $Script:resource.Products | should BeNullOrEmpty + $Script:resource.Products | should -BeNullOrEmpty } it "Computer Groups" { - $Script:resource.ComputerGroups | should BeNullOrEmpty + $Script:resource.ComputerGroups | should -BeNullOrEmpty } it "Enabled" { - $Script:resource.Enabled | should BeNullOrEmpty + $Script:resource.Enabled | should -BeNullOrEmpty } it "mocks were called" { @@ -126,27 +129,27 @@ try Context 'server is not configured.' { it 'calling Get should not throw' { - {$Script:resource = Get-TargetResource -Name 'Foo' -verbose} | should not throw + {$Script:resource = Get-TargetResource -Name 'Foo' -verbose} | should -not -throw } it "Ensure" { - $Script:resource.Ensure | should be 'Absent' + $Script:resource.Ensure | should -Be 'Absent' } it "Classifications" { - $Script:resource.Classifications | should be $null + $Script:resource.Classifications | should -Be $null } it "Products" { - $Script:resource.Products | should be $null + $Script:resource.Products | should -Be $null } it "Computer Groups" { - $Script:resource.ComputerGroups | should be $null + $Script:resource.ComputerGroups | should -Be $null } it "Enabled" { - $Script:resource.Enabled | should be $null + $Script:resource.Enabled | should -Be $null } it "mocks were not called" { @@ -161,55 +164,65 @@ try #region Function Test-TargetResource Describe "MSFT_UpdateServicesApprovalRule\Test-TargetResource" { Context 'server is in correct state (Ensure=Present)' { - $DSCTestValues.Remove('Ensure') - $DSCTestValues.Add('Ensure','Present') - $script:result = $null + BeforeAll { + $DSCTestValues.Remove('Ensure') + $DSCTestValues.Add('Ensure','Present') + $script:result = $null + } it 'calling test should not throw' { - {$script:result = Test-TargetResource @DSCTestValues -verbose} | should not throw + {$script:result = Test-TargetResource @DSCTestValues -verbose} | should -not -throw } it "result should be true" { - $script:result | should be $true + $script:result | should -Be $true } } Context 'server should not be configured (Ensure=Absent) but is' { - - $DSCTestValues.Remove('Ensure') - $DSCTestValues.Add('Ensure','Absent') - $script:result = $null + BeforeAll { + $DSCTestValues.Remove('Ensure') + $DSCTestValues.Add('Ensure','Absent') + $script:result = $null + } it 'calling test should not throw' { - {$script:result = Test-TargetResource @DSCTestValues -verbose} | should not throw + {$script:result = Test-TargetResource @DSCTestValues -verbose} | should -not -throw } it "result should be false" { - $script:result | should be $false + $script:result | should -BeFalse } } Context "setting has drifted" { - $DSCTestValues.Remove('Ensure') - $DSCTestValues.Add('Ensure','Present') + BeforeAll { + $DSCTestValues.Remove('Ensure') + $DSCTestValues.Add('Ensure','Present') + } + $settingsList = 'Classifications','Products','ComputerGroups' - foreach ($setting in $settingsList) - { - $valueWithoutDrift = $DSCSetValues.$setting - $DSCTestValues.Remove("$setting") - $DSCTestValues.Add("$setting",'foo') - $script:result = $null + Context 'When <_> property is drifted' -Foreach $settingsList { + BeforeAll { + #$valueWithoutDrift = $DSCTestValues.$_ + + } it 'calling test should not throw' { - {$script:result = Test-TargetResource @DSCTestValues -verbose} | should not throw + $DSCTestValuesDrifted = $DSCTestValues.Clone() + $DSCTestValuesDrifted["$_"] = 'foo' + $script:result = $null + {$script:result = Test-TargetResource @DSCTestValuesDrifted -verbose} | should -Not -Throw } it "result should be false when $setting has changed" { - $script:result | should be $false + $script:result | should -BeFalse } - $DSCTestValues.Remove("$setting") - $DSCTestValues.Add("$setting",$valueWithoutDrift) + BeforeAll { + #$DSCTestValues.Remove("$_") + #$DSCTestValues.Add("$_",$valueWithoutDrift) + } } } } @@ -217,103 +230,106 @@ try #region Function Set-TargetResource Describe "MSFT_UpdateServicesApprovalRule\Set-TargetResource" { - $Collection = [pscustomobject]@{} - $Collection | Add-Member -MemberType ScriptMethod -Name Add -Value {} + BeforeAll { + $Collection = [pscustomobject]@{} + $Collection | Add-Member -MemberType ScriptMethod -Name Add -Value {} + } Context 'server is already in a correct state (resource is idempotent)' { - Mock New-Object -mockwith {$Collection} - Mock Get-WsusProduct -mockwith {} - Mock -CommandName New-InvalidOperationException -MockWith {} - Mock -CommandName New-InvalidResultException -MockWith {} - Mock -CommandName New-InvalidArgumentException -MockWith {} + BeforeAll { + Mock New-Object -mockwith {$Collection} + Mock Get-WsusProduct -mockwith {} + Mock -CommandName New-InvalidOperationException -MockWith {} + Mock -CommandName New-InvalidResultException -MockWith {} + Mock -CommandName New-InvalidArgumentException -MockWith {} + } it 'should not throw when running on a properly configured server' { - {Set-targetResource @DSCSetValues -verbose} | should not throw - } + {Set-targetResource @DSCSetValues -verbose} | should -Not -Throw - it "mocks were called" { - Assert-MockCalled -CommandName New-Object -Times 1 - Assert-MockCalled -CommandName Get-WsusProduct -Times 1 - } + #mock were called + Should -Invoke New-Object -Exactly 3 + Should -Invoke Get-WsusProduct -Exactly 1 - it "mocks were not called" { - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 - Assert-MockCalled -CommandName New-InvalidArgumentException -Times 0 - Assert-MockCalled -CommandName New-InvalidOperationException -Times 0 + #mock are not called + Should -Invoke New-InvalidResultException -Exactly 0 + Should -Invoke New-InvalidArgumentException -Exactly 0 + Should -Invoke New-InvalidOperationException -Exactly 0 } } Context 'server is not in a correct state (resource takes action)' { - - Mock New-Object -mockwith {$Collection} - Mock Get-WsusProduct -mockwith {} - Mock -CommandName New-InvalidOperationException -MockWith {} - Mock -CommandName New-InvalidResultException -MockWith {} - Mock -CommandName New-InvalidArgumentException -MockWith {} - Mock Test-TargetResource -mockwith {$true} + BeforeAll { + Mock New-Object -mockwith {$Collection} + Mock Get-WsusProduct -mockwith {} + Mock -CommandName New-InvalidOperationException -MockWith {} + Mock -CommandName New-InvalidResultException -MockWith {} + Mock -CommandName New-InvalidArgumentException -MockWith {} + Mock Test-TargetResource -mockwith {$true} + } it 'should not throw when running on an incorrectly configured server' { - {Set-targetResource -Name "Foo" -Classification "00000000-0000-0000-0000-0000testguid" -verbose} | should not throw - } + {Set-targetResource -Name "Foo" -Classification "00000000-0000-0000-0000-0000testguid" -verbose} | should -Not -Throw - it "mocks were called" { - Assert-MockCalled -CommandName New-Object -Times 1 - Assert-MockCalled -CommandName Test-TargetResource -Times 1 - Assert-MockCalled -CommandName Get-WsusProduct -Times 1 - } + #mock were called + Should -Invoke New-Object -Exactly 3 + Should -Invoke Test-TargetResource -Exactly 1 + Should -Invoke Get-WsusProduct -Exactly 1 - it "mocks were not called" { - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 - Assert-MockCalled -CommandName New-InvalidArgumentException -Times 0 - Assert-MockCalled -CommandName New-InvalidOperationException -Times 0 + #mock are not called + Should -Invoke New-InvalidResultException -Exactly 0 + Should -Invoke New-InvalidArgumentException -Exactly 0 + Should -Invoke New-InvalidOperationException -Exactly 0 } } Context 'server should not be configured (Ensure=Absent)' { - Mock New-Object -mockwith {$Collection} - Mock Get-WsusProduct -mockwith {} - Mock -CommandName New-InvalidOperationException -MockWith {} - Mock -CommandName New-InvalidResultException -MockWith {} - Mock -CommandName New-InvalidArgumentException -MockWith {} - Mock Test-TargetResource -mockwith {$true} + BeforeAll { + Mock New-Object -mockwith {$Collection} + Mock Get-WsusProduct -mockwith {} + Mock -CommandName New-InvalidOperationException -MockWith {} + Mock -CommandName New-InvalidResultException -MockWith {} + Mock -CommandName New-InvalidArgumentException -MockWith {} + Mock Test-TargetResource -mockwith {$true} + } it 'should not throw when running on an incorrectly configured server' { - {Set-targetResource @DSCSetValues -Ensure Absent -verbose} | should not throw - } + {Set-targetResource @DSCSetValues -Ensure Absent -verbose} | should -Not -Throw - it "mocks were called" { - Assert-MockCalled -CommandName Test-TargetResource -Times 1 - } + #mock were called + Should -Invoke Test-TargetResource -Exactly 1 - it "mocks were not called" { - Assert-MockCalled -CommandName New-Object -Times 0 - Assert-MockCalled -CommandName Get-WsusProduct -Times 0 - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 - Assert-MockCalled -CommandName New-InvalidArgumentException -Times 0 - Assert-MockCalled -CommandName New-InvalidOperationException -Times 0 + #mock are not called + Should -Invoke New-Object -Exactly 0 + Should -Invoke Get-WsusProduct -Exactly 0 + Should -Invoke New-InvalidResultException -Exactly 0 + Should -Invoke New-InvalidArgumentException -Exactly 0 + Should -Invoke New-InvalidOperationException -Exactly 0 } } Context 'server is in correct state and synchronize is included' { - Mock New-Object -mockwith {$Collection} - Mock Get-WsusProduct -mockwith {} - Mock -CommandName New-InvalidOperationException -MockWith {} - Mock -CommandName New-InvalidResultException -MockWith {} - Mock -CommandName New-InvalidArgumentException -MockWith {} + BeforeAll { + Mock New-Object -mockwith {$Collection} + Mock Get-WsusProduct -mockwith {} + Mock -CommandName New-InvalidOperationException -MockWith {} + Mock -CommandName New-InvalidResultException -MockWith {} + Mock -CommandName New-InvalidArgumentException -MockWith {} + Mock Test-TargetResource -mockwith {$true} + } it 'should not throw when running on a properly configured server' { - {Set-targetResource @DSCSetValues -Synchronize $true -verbose} | should not throw - } + {Set-targetResource @DSCSetValues -Synchronize $true -verbose} | should -Not -Throw - it "mocks were called" { - Assert-MockCalled -CommandName New-Object -Times 1 - Assert-MockCalled -CommandName Get-WsusProduct -Times 1 - } + #mock were called + Should -Invoke New-Object -Exactly 3 + Should -Invoke Test-TargetResource -Exactly 1 + Should -Invoke Get-WsusProduct -Exactly 1 - it "mocks were not called" { - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 - Assert-MockCalled -CommandName New-InvalidArgumentException -Times 0 - Assert-MockCalled -CommandName New-InvalidOperationException -Times 0 + #mock are not called + Should -Invoke New-InvalidResultException -Exactly 0 + Should -Invoke New-InvalidArgumentException -Exactly 0 + Should -Invoke New-InvalidOperationException -Exactly 0 } } } diff --git a/Tests/Unit/MSFT_UpdateServicesCleanup.tests.ps1 b/Tests/Unit/MSFT_UpdateServicesCleanup.tests.ps1 index 67a23d6..9d1abf7 100644 --- a/Tests/Unit/MSFT_UpdateServicesCleanup.tests.ps1 +++ b/Tests/Unit/MSFT_UpdateServicesCleanup.tests.ps1 @@ -23,121 +23,132 @@ try # The InModuleScope command allows you to perform white-box unit testing on the internal # (non-exported) code of a Script Module. InModuleScope $script:DSCResourceName { - $DSCSetValues = - @{ - DeclineSupersededUpdates = $true - DeclineExpiredUpdates = $true - CleanupObsoleteUpdates = $true - CompressUpdates = $true - CleanupObsoleteComputers = $true - CleanupUnneededContentFiles = $true - CleanupLocalPublishedContentFiles = $true - TimeOfDay = "04:00:00" - } + BeforeAll { + $DSCSetValues = + @{ + DeclineSupersededUpdates = $true + DeclineExpiredUpdates = $true + CleanupObsoleteUpdates = $true + CompressUpdates = $true + CleanupObsoleteComputers = $true + CleanupUnneededContentFiles = $true + CleanupLocalPublishedContentFiles = $true + TimeOfDay = "04:00:00" + } - $DSCTestValues = - @{ - DeclineSupersededUpdates = $true - DeclineExpiredUpdates = $true - CleanupObsoleteUpdates = $true - CompressUpdates = $true - CleanupObsoleteComputers = $true - CleanupUnneededContentFiles = $true - CleanupLocalPublishedContentFiles = $true - TimeOfDay = "04:00:00" + $DSCTestValues = + @{ + DeclineSupersededUpdates = $true + DeclineExpiredUpdates = $true + CleanupObsoleteUpdates = $true + CompressUpdates = $true + CleanupObsoleteComputers = $true + CleanupUnneededContentFiles = $true + CleanupLocalPublishedContentFiles = $true + TimeOfDay = "04:00:00" + } } #endregion #region Function Get-TargetResource expecting Ensure Present Describe "MSFT_UpdateServicesCleanup\Get-TargetResource" { - $Arguments = 'foo"$DeclineSupersededUpdates = $True;$DeclineExpiredUpdates = $True;$CleanupObsoleteUpdates = $True;$CompressUpdates = $True;$CleanupObsoleteComputers = $True;$CleanupUnneededContentFiles = $True;$CleanupLocalPublishedContentFiles = $True' - $Execute = "$($env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe" - $StartBoundary = '20160101T04:00:00' + BeforeAll { + $Arguments = 'foo"$DeclineSupersededUpdates = $True;$DeclineExpiredUpdates = $True;$CleanupObsoleteUpdates = $True;$CompressUpdates = $True;$CleanupObsoleteComputers = $True;$CleanupUnneededContentFiles = $True;$CleanupLocalPublishedContentFiles = $True' + $Execute = "$($env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe" + $StartBoundary = '20160101T04:00:00' + } Context 'server is configured.' { - Mock -CommandName Get-ScheduledTask -mockwith { - @{ - State = 'Enabled' - Actions = + BeforeAll { + Mock -CommandName Get-ScheduledTask -mockwith { @{ - Execute = $Execute - Arguments = $Arguments - } - Triggers = - @{ - StartBoundary = $StartBoundary + State = 'Enabled' + Actions = + @{ + Execute = $Execute + Arguments = $Arguments + } + Triggers = + @{ + StartBoundary = $StartBoundary + } } - } - } -Verifiable + } -Verifiable + } it 'calling Get should not throw' { - {$Script:resource = Get-TargetResource -Ensure "Present" -verbose} | should not throw - } + {$Script:resource = Get-TargetResource -Ensure "Present" -verbose} | Should -Not -Throw - it 'Ensure' { - $Script:resource.Ensure | should be 'Present' + Should -Invoke Get-ScheduledTask -Exactly 1 } - $settingsList = 'DeclineSupersededUpdates','DeclineExpiredUpdates','CleanupObsoleteUpdates','CompressUpdates','CleanupObsoleteComputers','CleanupUnneededContentFiles','CleanupLocalPublishedContentFiles' - foreach ($setting in $settingsList) - { - it "$setting should be true" { - $Script:resource.$setting | Should Be 'True' + it 'Ensure' { + $Script:resource.Ensure | should -Be 'Present' + } + + $settingsList = @( + 'DeclineSupersededUpdates' + 'DeclineExpiredUpdates' + 'CleanupObsoleteUpdates' + 'CompressUpdates' + 'CleanupObsoleteComputers' + 'CleanupUnneededContentFiles' + 'CleanupLocalPublishedContentFiles' + ) + + Context 'When <_> property is valid' -Foreach $settingsList { + it '<_> should be true' { + $Script:resource.$_ | Should -BeTrue } } it 'TimeOfDay' { - $Script:resource.TimeOfDay | Should Be $StartBoundary.Split('T')[1] - } - - it 'mocks were called' { - Assert-VerifiableMock + $Script:resource.TimeOfDay | Should -Be $StartBoundary.Split('T')[1] } } Context 'server is not configured.' { - Mock Get-ScheduledTask -mockwith {} -Verifiable + BeforeAll { + Mock Get-ScheduledTask -mockwith {} -Verifiable + } it 'calling Get should not throw' { - {$Script:resource = Get-TargetResource -Ensure 'Absent' -verbose} | should not throw - } + {$Script:resource = Get-TargetResource -Ensure 'Absent' -verbose} | should -Not -Throw - it 'Ensure' { - $Script:resource.Ensure | should be 'Absent' + Should -Invoke Get-ScheduledTask -Exactly 1 } - it 'mocks were called' { - Assert-VerifiableMock + it 'Ensure' { + $Script:resource.Ensure | should -Be 'Absent' } } Context 'server is configured in an unexpected way.' { - - Mock Get-ScheduledTask -mockwith { - @{ - State = 'Disabled' - Actions = + BeforeAll { + Mock Get-ScheduledTask -mockwith { @{ - Execute = $Execute - Arguments = $Arguments + State = 'Disabled' + Actions = + @{ + Execute = $Execute + Arguments = $Arguments + } + Triggers = + @{ + StartBoundary = $StartBoundary } - Triggers = - @{ - StartBoundary = $StartBoundary } } - } -Verifiable + } it 'calling Get should not throw' { - {$Script:resource = Get-TargetResource -Ensure 'Present' -verbose} | should not throw - } + {$Script:resource = Get-TargetResource -Ensure 'Present' -verbose} | should -Not -Throw - it 'Ensure' { - $Script:resource.Ensure | should be 'Absent' + Should -Invoke Get-ScheduledTask -Exactly 1 } - it 'mocks were called' { - Assert-VerifiableMock + it 'Ensure' { + $Script:resource.Ensure | should -Be 'Absent' } } } @@ -147,89 +158,102 @@ try #region Function Test-TargetResource Describe "MSFT_UpdateServicesCleanup\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 + BeforeAll { + $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 - } + {$script:result = Test-TargetResource @DSCTestValues -verbose} | should -Not -Throw - it "result should be true" { - $script:result | should be $true + Should -Invoke Get-TargetResource -Exactly 1 } - it 'mocks were called' { - Assert-VerifiableMock + it "result should be true" { + $script:result | should -BeTrue } } 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 + BeforeAll { + $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 - } + {$script:result = Test-TargetResource @DSCTestValues -verbose} | should -Not -Throw - it "result should be true" { - $script:result | should be $true + Should -Invoke Get-TargetResource -Exactly 1 } - it 'mocks were called' { - Assert-VerifiableMock + it "result should be true" { + $script:result | should -BeTrue } } Context 'server should be configured correctly but is not' { - - $DSCTestValues.Remove('Ensure') - Mock -CommandName Get-TargetResource -MockWith {$DSCTestValues} -Verifiable - $script:result = $null + BeforeAll { + $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 - } + {$script:result = Test-TargetResource @DSCTestValues -Ensure 'Present' -verbose} | should -Not -Throw - it "result should be false" { - $script:result | should be $false + Should -Invoke Get-TargetResource -Exactly 1 } - it 'mocks were called' { - Assert-VerifiableMock + it "result should be false" { + $script:result | should -BeFalse } } Context "setting has drifted" { - $DSCTestValues.Remove('Ensure') - $DSCTestValues.Add('Ensure','Present') - $settingsList = 'DeclineSupersededUpdates','DeclineExpiredUpdates','CleanupObsoleteUpdates','CompressUpdates','CleanupObsoleteComputers','CleanupUnneededContentFiles','CleanupLocalPublishedContentFiles' - foreach ($setting in $settingsList) - { - Mock -CommandName Get-TargetResource -MockWith { - $DSCTestValues.Remove("$setting") - $DSCTestValues - } -Verifiable + BeforeAll { + $DSCTestValues.Remove('Ensure') + $DSCTestValues.Add('Ensure','Present') + } + + $settingsList = @( + 'DeclineSupersededUpdates' + 'DeclineExpiredUpdates' + 'CleanupObsoleteUpdates' + 'CompressUpdates' + 'CleanupObsoleteComputers' + 'CleanupUnneededContentFiles' + 'CleanupLocalPublishedContentFiles' + ) + + Context 'When <_> property is invalid' -Foreach $settingsList { + BeforeAll { + $setting = $_ + Mock -CommandName Get-TargetResource -MockWith { + $DSCTestValuesClone = $DSCTestValues.Clone() + $DSCTestValuesClone.Remove("$setting") + $DSCTestValuesClone + } - $script:result = $null + $script:result = $null + } it 'calling test should not throw' { - {$script:result = Test-TargetResource @DSCTestValues -verbose} | 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 + Should -Invoke Get-TargetResource -Exactly 1 } - it 'mocks were called' { - Assert-VerifiableMock + it "result should be false when <_> has changed" { + $script:result | should -BeFalse } - $DSCTestValues.Add("$setting",$true) + AfterAll { + #$DSCTestValues.Add("$setting",$true) + } } } } @@ -237,79 +261,78 @@ try #region Function Set-TargetResource Describe "MSFT_UpdateServicesCleanup\Set-TargetResource" { - $Arguments = 'foo"$DeclineSupersededUpdates = $True;$DeclineExpiredUpdates = $True;$CleanupObsoleteUpdates = $True;$CompressUpdates = $True;$CleanupObsoleteComputers = $True;$CleanupUnneededContentFiles = $True;$CleanupLocalPublishedContentFiles = $True' - $Execute = "$($env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe" - $StartBoundary = '20160101T04:00:00' - Mock -CommandName Unregister-ScheduledTask -MockWith {} - Mock -CommandName Register-ScheduledTask -MockWith {} - Mock -CommandName Test-TargetResource -MockWith {$true} - Mock -CommandName New-InvalidResultException -MockWith {} + BeforeAll { + $Arguments = 'foo"$DeclineSupersededUpdates = $True;$DeclineExpiredUpdates = $True;$CleanupObsoleteUpdates = $True;$CompressUpdates = $True;$CleanupObsoleteComputers = $True;$CleanupUnneededContentFiles = $True;$CleanupLocalPublishedContentFiles = $True' + $Execute = "$($env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe" + $StartBoundary = '20160101T04:00:00' + Mock -CommandName Unregister-ScheduledTask -MockWith {} + Mock -CommandName Register-ScheduledTask -MockWith {} + Mock -CommandName Test-TargetResource -MockWith {$true} + Mock -CommandName New-InvalidResultException -MockWith {} + } Context 'resource is idempotent (Ensure=Present)' { - Mock -CommandName Get-ScheduledTask -MockWith {$true} + BeforeAll { + Mock -CommandName Get-ScheduledTask -MockWith {$true} + } it 'should not throw when running on a properly configured server' { - {Set-targetResource @DSCSetValues -Ensure Present -verbose} | should not throw - } + {Set-targetResource @DSCSetValues -Ensure Present -verbose} | should -Not -Throw - it "mocks were called for commands that gather information" { - Assert-MockCalled -CommandName Get-ScheduledTask -Times 1 - Assert-MockCalled -CommandName Unregister-ScheduledTask -Times 1 - Assert-MockCalled -CommandName Register-ScheduledTask -Times 1 - Assert-MockCalled -CommandName Test-TargetResource -Times 1 - } + #mocks were called for commands that gather information + Should -Invoke Get-ScheduledTask -Exactly 1 + Should -Invoke Unregister-ScheduledTask -Exactly 1 + Should -Invoke Register-ScheduledTask -Exactly 1 + Should -Invoke Test-TargetResource -Exactly 1 - it "mocks were called that register a task to run WSUS cleanup" { - Assert-MockCalled -CommandName Register-ScheduledTask -Times 1 - } + #mocks were called that register a task to run WSUS cleanup + Should -Invoke Register-ScheduledTask -Exactly 1 - it "mocks were not called that remove tasks or log errors" { - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 + #mocks were not called that remove tasks or log errors + Should -Invoke New-InvalidResultException -Exactly 0 } } Context 'resource processes Set tasks to register Cleanup task (Ensure=Present)' { - Mock -CommandName Get-ScheduledTask -MockWith {} + BeforeAll { + Mock -CommandName Get-ScheduledTask -MockWith {} + } it 'should not throw when running on a properly configured server' { - {Set-targetResource @DSCSetValues -Ensure Present -verbose} | should not throw - } + {Set-targetResource @DSCSetValues -Ensure Present -verbose} | should -Not -Throw - it "mocks were called for commands that gather information" { - Assert-MockCalled -CommandName Get-ScheduledTask -Times 1 - Assert-MockCalled -CommandName Register-ScheduledTask -Times 1 - Assert-MockCalled -CommandName Test-TargetResource -Times 1 - } + #mocks were called for commands that gather information + Should -Invoke Get-ScheduledTask -Exactly 1 + Should -Invoke Register-ScheduledTask -Exactly 1 + Should -Invoke Test-TargetResource -Exactly 1 - it "mocks were called that register a task to run WSUS cleanup" { - Assert-MockCalled -CommandName Register-ScheduledTask -Times 1 - } + #mocks were called that register a task to run WSUS cleanup + Should -Invoke Register-ScheduledTask -Exactly 1 - it "mocks were not called that remove tasks or log errors" { - Assert-MockCalled -CommandName Unregister-ScheduledTask -Times 0 - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 + #mocks were not called that remove tasks or log errors + Should -Invoke Unregister-ScheduledTask -Exactly 0 + Should -Invoke New-InvalidResultException -Exactly 0 } } Context 'resource processes Set tasks to remove Cleanup task (Ensure=Absent)' { - Mock -CommandName Get-ScheduledTask -MockWith {$true} + BeforeAll { + Mock -CommandName Get-ScheduledTask -MockWith {$true} + } it 'should not throw when running on a properly configured server' { - {Set-targetResource @DSCSetValues -Ensure Absent -verbose} | should not throw - } + {Set-targetResource @DSCSetValues -Ensure Absent -verbose} | should -Not -Throw - it "mocks were called for commands that gather information" { - Assert-MockCalled -CommandName Get-ScheduledTask -Times 1 - Assert-MockCalled -CommandName Test-TargetResource -Times 1 - } + #mocks were called for commands that gather information + Should -Invoke Get-ScheduledTask -Exactly 1 + Should -Invoke Test-TargetResource -Exactly 1 - it "mocks were called to remove Cleanup task" { - Assert-MockCalled -CommandName Unregister-ScheduledTask -Times 1 - } + #mocks were called that register a task to run WSUS cleanup + Should -Invoke Unregister-ScheduledTask -Exactly 1 - it "mocks were not called that register tasks or log errors" { - Assert-MockCalled -CommandName Register-ScheduledTask -Times 0 - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 + #mocks were not called that remove tasks or log errors + Should -Invoke Register-ScheduledTask -Exactly 0 + Should -Invoke New-InvalidResultException -Exactly 0 } } } diff --git a/Tests/Unit/MSFT_UpdateServicesServer.tests.ps1 b/Tests/Unit/MSFT_UpdateServicesServer.tests.ps1 index ac9dea0..7fbd08c 100644 --- a/Tests/Unit/MSFT_UpdateServicesServer.tests.ps1 +++ b/Tests/Unit/MSFT_UpdateServicesServer.tests.ps1 @@ -12,6 +12,9 @@ $TestEnvironment = Initialize-TestEnvironment ` -ResourceType 'Mof' ` -TestType Unit +#region Pester Test Initialization +Import-Module $PSScriptRoot\..\Helpers\ImitateUpdateServicesModule.psm1 -force -ErrorAction Stop + #endregion HEADER # Begin Testing @@ -22,93 +25,88 @@ try # The InModuleScope command allows you to perform white-box unit testing on the internal # (non-exported) code of a Script Module. InModuleScope $script:DSCResourceName { + BeforeAll { + $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 + ClientTargetingMode = "Client" + } - #region Pester Test Initialization - Import-Module $PSScriptRoot\..\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 - ClientTargetingMode = "Client" - } - - $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 - ClientTargetingMode = "Client" + $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 + ClientTargetingMode = "Client" + } } #endregion #region Function Get-TargetResource expecting Ensure Present Describe "MSFT_UpdateServicesServer\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 + BeforeAll{ + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Microsoft\Update Services\Server\Setup' -and $Name -eq 'SQLServerName' } -MockWith { @{SQLServerName = 'SQLServer' } } + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Microsoft\Update Services\Server\Setup' -and $Name -eq 'ContentDir' } -MockWith { @{ContentDir = 'C:\WSUSContent\' } } + } Context 'server should be configured.' { - It 'calling Get should not throw' { - { $Script:resource = Get-TargetResource -Ensure 'Present' -verbose } | Should not throw + It 'calling Get should not throw and mocks' { + { $Script:resource = Get-TargetResource -Ensure 'Present' -verbose } | Should -Not -Throw + + Should -Invoke Get-ItemProperty -Exactly 2 } It 'sets the value for Ensure' { - $Script:resource.Ensure | Should be 'Present' + $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 "returns good values in Get results" { + foreach ($setting in $DSCSetValues.Keys) + { + $Script:resource.$setting | Should -Be $DSCGetValues.$setting } } - - It 'mocks were called' { - Assert-VerifiableMock - } } - Context 'server should not be configured.' { + Context 'server should not configured.' { - It 'calling Get should not throw' { + It 'calling Get should not throw and mocks' { Mock -CommandName Get-WSUSServer -MockWith { } - { $Script:resource = Get-TargetResource -Ensure 'Absent' -verbose } | Should not throw - } + { $Script:resource = Get-TargetResource -Ensure 'Absent' -verbose } | Should -Not -Throw - It 'sets the value for Ensure' { - $Script:resource.Ensure | Should be 'Absent' + Should -Invoke Get-WsusServer -Exactly 1 } - It 'mocks were called' { - Assert-VerifiableMock + It 'sets the value for Ensure' { + $Script:resource.Ensure | Should -Be 'Absent' } } @@ -122,8 +120,10 @@ try $script:result = $null } - It 'calling test should not throw' { - { $script:result = Get-TargetResource -Ensure 'Present' -verbose } | Should not throw + It 'calling test should not throw and mocks' { + { $script:result = Get-TargetResource -Ensure 'Present' -verbose } | Should -Not -Throw + + Should -Invoke Get-WsusServer -Exactly 1 } It "Products should contain right value" { @@ -135,10 +135,6 @@ try $script:result.Products | Should -Contain $_ } } - - It 'mocks were called' { - Assert-VerifiableMock - } } } #endregion @@ -147,20 +143,22 @@ try Describe "MSFT_UpdateServicesServer\Test-TargetResource" { Context 'server is in correct state (Ensure=Present)' { + BeforeAll { + $DSCTestValues.Remove('Ensure') + $DSCTestValues.Add('Ensure', 'Present') - $DSCTestValues.Remove('Ensure') - $DSCTestValues.Add('Ensure', 'Present') - - Mock -CommandName Get-TargetResource -MockWith { $DSCTestValues } -Verifiable - - $script:result = $null + 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 + { $script:result = Test-TargetResource @DSCTestValues -verbose } | Should -Not -Throw + + Should -Invoke Get-TargetResource -Exactly 1 } It "result should be true" { - $script:result | Should be $true + $script:result | Should -BeTrue } It 'mocks were called' { @@ -169,77 +167,87 @@ try } Context 'server should not be configured (Ensure=Absent)' { + BeforeAll { + $DSCTestValues.Remove('Ensure') + $DSCTestValues.Add('Ensure', 'Absent') - $DSCTestValues.Remove('Ensure') - $DSCTestValues.Add('Ensure', 'Absent') - - Mock -CommandName Get-TargetResource -MockWith { $DSCTestValues } -Verifiable - - $script:result = $null + 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 - } + { $script:result = Test-TargetResource @DSCTestValues -verbose } | Should -Not -Throw - It "result should be true" { - $script:result | Should be $true + Should -Invoke Get-TargetResource -Exactly 1 } - It 'mocks were called' { - Assert-VerifiableMock + It "result should be true" { + $script:result | Should -Be true } } Context 'server should be configured correctly but is not' { + BeforeAll { + $DSCTestValues.Remove('Ensure') + Mock -CommandName Get-TargetResource -MockWith { $DSCTestValues } -Verifiable - $DSCTestValues.Remove('Ensure') - - Mock -CommandName Get-TargetResource -MockWith { $DSCTestValues } -Verifiable - - $script:result = $null + $script:result = $null + } It 'calling test should not throw' { - { $script:result = Test-TargetResource @DSCTestValues -Ensure 'Present' -verbose } | Should not throw - } + { $script:result = Test-TargetResource @DSCTestValues -Ensure 'Present' -verbose } | Should -Not -Throw - It "result should be false" { - $script:result | Should be $false + Should -Invoke Get-TargetResource -Exactly 1 } - It 'mocks were called' { - Assert-VerifiableMock + It "result should be false" { + $script:result | Should -BeFalse } } Context "setting has drifted" { - - $DSCTestValues.Remove('Ensure') - $DSCTestValues.Add('Ensure', 'Present') + BeforeAll { + $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 + $settingsList = @( + 'UpdateImprovementProgram' + 'UpstreamServerName' + 'UpstreamServerPort' + 'UpstreamServerSSL' + 'UpstreamServerReplica' + 'ProxyServerName' + 'ProxyServerPort' + 'SynchronizeAutomaticallyTimeOfDay' + 'SynchronizationsPerDay' + ) + + Context "When <_> property is invalid" -Foreach $settingsList { + BeforeAll { + $setting = $_ + Mock -CommandName Get-TargetResource -MockWith { + $DSCTestValues.Remove("$setting") + $DSCTestValues + } + } $script:result = $null - It "calling test with change to $setting should not throw" { - { $script:result = Test-TargetResource @DSCTestValues -verbose } | Should not throw - } + It "calling test with change to <_> 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 + Should -Invoke Get-TargetResource -Exactly 1 } - It 'mocks were called' { - Assert-VerifiableMock + It "result should be false when <_> has changed" { + $script:result | Should -Be $false } - $DSCTestValues.Add("$setting", $true) + AfterAll { + $DSCTestValues.Add("$_", $true) + } } } @@ -298,15 +306,11 @@ try } It 'calling test should not throw' { - { $script:result = Test-TargetResource @DSCTestValues -Ensure 'Present' -verbose } | Should not throw + { $script:result = Test-TargetResource @DSCTestValues -Ensure 'Present' -verbose } | Should -Not -Throw } It "result should be true" { - $script:result | Should be $true - } - - It 'mocks were called' { - Assert-VerifiableMock + $script:result | Should -Be $true } } } @@ -314,44 +318,35 @@ try #region Function Set-TargetResource Describe "MSFT_UpdateServicesServer\Set-TargetResource" { + BeforeAll { + $DSCTestValues.Remove('Ensure') - $DSCTestValues.Remove('Ensure') - - Mock -CommandName Test-TargetResource -MockWith { $true } - Mock -CommandName New-InvalidOperationException -MockWith { } - Mock -CommandName New-InvalidResultException -MockWith { } - Mock SaveWsusConfiguration -MockWith { } - + Mock -CommandName Test-TargetResource -MockWith { $true } + Mock -CommandName New-InvalidOperationException -MockWith { } + Mock -CommandName New-InvalidResultException -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 - } + { 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-InvalidResultException -Times 0 - Assert-MockCalled -CommandName New-InvalidOperationException -Times 0 + Should -Invoke Test-TargetResource -Exactly 1 + Should -Invoke SaveWsusConfiguration -Exactly 2 + Should -Invoke New-InvalidResultException -Exactly 0 + Should -Invoke New-InvalidOperationException -Exactly 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 - } + { 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 - } + Should -Invoke Test-TargetResource -Exactly 1 + Should -Invoke SaveWsusConfiguration -Exactly 2 - It "mocks were not called that log errors" { - Assert-MockCalled -CommandName New-InvalidResultException -Times 0 + Should -Invoke New-InvalidResultException -Exactly 0 } } } diff --git a/build.yaml b/build.yaml index 1e7888b..f5d5df8 100644 --- a/build.yaml +++ b/build.yaml @@ -38,10 +38,11 @@ BuildWorkflow: - package_module_nupkg hqrmtest: - - DscResource_Tests_Stop_On_Fail + - Invoke_HQRM_Tests_Stop_On_Fail test: - Pester_Tests_Stop_On_Fail + - Convert_Pester_Coverage - Pester_if_Code_Coverage_Under_Threshold publish: @@ -51,35 +52,54 @@ BuildWorkflow: Pester: #Passthru, OutputFile, CodeCoverageOutputFile not supported - OutputFormat: NUnitXML + Configuration: + Run: + Path: + - tests/Unit + - tests/QA + Output: + Verbosity: Detailed + StackTraceVerbosity: Full + CIFormat: Auto + CodeCoverage: + CoveragePercentTarget: 50 + OutputPath: JaCoCo_coverage.xml + OutputEncoding: ascii + # There is a bug in Pester when running unit tests for classes when 'UseBreakpoints' is turned off. + # See error in gist: https://gist.github.com/johlju/c16dfd9587c7e066e8825fc54b33a703 + UseBreakpoints: true + TestResult: + OutputFormat: NUnitXML + OutputEncoding: ascii ExcludeFromCodeCoverage: - Modules/DscResource.Common - Script: - # - tests/Unit/MSFT_UpdateServicesCleanup.tests.ps1 - # - tests/Unit/MSFT_UpdateServicesServer.tests.ps1 - # - tests/Unit/MSFT_UpdateServicesApprovalRule.tests.ps1 - - tests/Unit - - tests/QA - # - tests/Integration ExcludeTag: - helpQuality - FunctionalQuality - TestQuality - Tag: - CodeCoverageThreshold: 50 # Set to 0 to bypass - # CodeCoverageOutputFile: JaCoCo_$OsShortName.xml - # CodeCoverageOutputFileEncoding: ascii - # CodeCoverageMergedOutputFile: JaCoCo_Merged.xml +#################################################### +# Pester Configuration (DscResource.Test) # +#################################################### DscTest: - ExcludeTag: - - "Common Tests - New Error-Level Script Analyzer Rules" - Tag: - ExcludeSourceFile: - - output - ExcludeModuleFile: - - Modules/DscResource.Common - + Pester: + Configuration: + Filter: + ExcludeTag: + - "Common Tests - New Error-Level Script Analyzer Rules" + Output: + Verbosity: Detailed + CIFormat: Auto + TestResult: + OutputFormat: NUnitXML + OutputEncoding: ascii + OutputPath: ./output/testResults/NUnitXml_HQRM_Tests.xml + Script: + ExcludeSourceFile: + - output + ExcludeModuleFile: + - Modules/DscResource.Common + MainGitBranch: main ModuleBuildTasks: Sampler: @@ -88,6 +108,8 @@ ModuleBuildTasks: - '*.ib.tasks' DscResource.DocGenerator: - 'Task.*' + DscResource.Test: + - 'Task.*' # Invoke-Build Header to be used to 'decorate' the terminal output of the tasks. From 99cab6845a2117b39b8adda2f868220d91768320 Mon Sep 17 00:00:00 2001 From: gaelcolas Date: Wed, 8 Feb 2023 00:19:48 +0100 Subject: [PATCH 2/3] Updating HQRM issues --- source/Modules/PDT/PDT.psm1 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/Modules/PDT/PDT.psm1 b/source/Modules/PDT/PDT.psm1 index 6e76d7f..72050c3 100644 --- a/source/Modules/PDT/PDT.psm1 +++ b/source/Modules/PDT/PDT.psm1 @@ -4,17 +4,19 @@ $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' -FileName 'P # New-InvalidArgumentError # New-InvalidArgumentException -ArgumentName 'Action' -Message $errorMessage + <# .SYNOPSIS Resolves a path and verifies it exists. .PARAMETER Path - Path to resolve + Path to resolve and return to caller. #> function Invoke-ResolvePath { [CmdletBinding()] + [OutputType([string])] param ( [Parameter(Mandatory = $true)] @@ -152,6 +154,7 @@ function Test-RootedPath function Get-Arguments { [CmdletBinding()] + [OutputType([hasthable])] param ( [Parameter(Mandatory = $true)] @@ -166,7 +169,7 @@ function Get-Arguments $NewArgumentNames ) - $returnValue = @{ } + $returnValue = @{} for ($i = 0; $i -lt $ArgumentNames.Count; $i++) { From cf1c4a7b639efff59a0397fe1eb8b9bd343b5847 Mon Sep 17 00:00:00 2001 From: gaelcolas Date: Wed, 8 Feb 2023 00:29:08 +0100 Subject: [PATCH 3/3] trying other output type before I disable the check --- source/Modules/PDT/PDT.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Modules/PDT/PDT.psm1 b/source/Modules/PDT/PDT.psm1 index 72050c3..ec00fe6 100644 --- a/source/Modules/PDT/PDT.psm1 +++ b/source/Modules/PDT/PDT.psm1 @@ -154,7 +154,7 @@ function Test-RootedPath function Get-Arguments { [CmdletBinding()] - [OutputType([hasthable])] + [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)]