diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c3fcf29ed..ca4363f158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added integration tests for `Remove-SqlDscAudit` command to ensure it functions correctly in real environments [issue #2241](https://github.com/dsccommunity/SqlServerDsc/issues/2241). +- Added integration tests for `Import-SqlDscPreferredModule` command to ensure + proper module import functionality in real environments + [issue #2225](https://github.com/dsccommunity/SqlServerDsc/issues/2225). - Added integration tests for `Test-SqlDscIsSupportedFeature` command to ensure it functions correctly in real environments [issue #2228](https://github.com/dsccommunity/SqlServerDsc/issues/2228). diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b0a3cd95d9..d886501130 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -286,6 +286,7 @@ stages: # Run the integration tests in a specific group order. # Group 0 'tests/Integration/Commands/Prerequisites.Integration.Tests.ps1' + 'tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1' # Group 1 'tests/Integration/Commands/Install-SqlDscServer.Integration.Tests.ps1' 'tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1' @@ -403,6 +404,7 @@ stages: # Run the integration tests in a specific group order. # Group 0 'tests/Integration/Commands/Prerequisites.Integration.Tests.ps1' + 'tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1' # Group 1 'tests/Integration/Commands/Install-SqlDscReportingService.Integration.Tests.ps1' # Group 2 @@ -466,6 +468,7 @@ stages: # Run the integration tests in a specific group order. # Group 0 'tests/Integration/Commands/Prerequisites.Integration.Tests.ps1' + 'tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1' # Group 1 'tests/Integration/Commands/Install-SqlDscBIReportServer.Integration.Tests.ps1' # Group 2 diff --git a/tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1 b/tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1 new file mode 100644 index 0000000000..ae855aa19d --- /dev/null +++ b/tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1 @@ -0,0 +1,188 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have 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 have 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 noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop' +} + +Describe 'Import-SqlDscPreferredModule' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + # Store original environment variable value to restore later + $script:originalSMODefaultModuleName = $env:SMODefaultModuleName + + # Get list of initially loaded modules to restore session state + $script:initialModules = Get-Module | Where-Object { $_.Name -in @('SqlServer', 'SQLPS') } + } + + AfterAll { + # Restore original environment variable + if ($null -ne $script:originalSMODefaultModuleName) + { + $env:SMODefaultModuleName = $script:originalSMODefaultModuleName + } + else + { + Remove-Item -Path 'env:SMODefaultModuleName' -ErrorAction 'SilentlyContinue' + } + + # Clean up any modules that were imported during testing + $currentModules = Get-Module | Where-Object { $_.Name -in @('SqlServer', 'SQLPS') } + foreach ($module in $currentModules) + { + if ($module.Name -notin $script:initialModules.Name) + { + Remove-Module -Name $module.Name -Force -ErrorAction 'SilentlyContinue' + } + } + } + + Context 'When importing the default preferred module' { + BeforeEach { + # Remove any SQL modules that might be loaded + Get-Module -Name @('SqlServer', 'SQLPS') | Remove-Module -Force -ErrorAction 'SilentlyContinue' + } + + It 'Should import a module without throwing' { + { Import-SqlDscPreferredModule -ErrorAction 'Stop' } | Should -Not -Throw + } + + It 'Should import SqlServer module when available' { + Import-SqlDscPreferredModule -ErrorAction 'Stop' + + $importedModule = Get-Module -Name @('SqlServer', 'SQLPS') | Select-Object -First 1 + $importedModule | Should -Not -BeNullOrEmpty + $importedModule.Name | Should -BeIn @('SqlServer', 'SQLPS') + } + } + + Context 'When using the Force parameter' { + BeforeEach { + # Remove any SQL modules that might be loaded + Get-Module -Name @('SqlServer', 'SQLPS') | Remove-Module -Force -ErrorAction 'SilentlyContinue' + } + + It 'Should import a module without throwing when using Force' { + { Import-SqlDscPreferredModule -Force -ErrorAction 'Stop' } | Should -Not -Throw + } + + It 'Should reload module when Force is used' { + # First import + Import-SqlDscPreferredModule -ErrorAction 'Stop' + $firstImport = Get-Module -Name @('SqlServer', 'SQLPS') | Select-Object -First 1 + + # Force reimport + Import-SqlDscPreferredModule -Force -ErrorAction 'Stop' + $secondImport = Get-Module -Name @('SqlServer', 'SQLPS') | Select-Object -First 1 + + $secondImport | Should -Not -BeNullOrEmpty + $secondImport.Name | Should -Be $firstImport.Name + } + } + + Context 'When specifying a preferred module name' { + BeforeEach { + # Remove any SQL modules that might be loaded + Get-Module -Name @('SqlServer', 'SQLPS') | Remove-Module -Force -ErrorAction 'SilentlyContinue' + } + + It 'Should import SQLPS when specifically requested' { + # Skip if SQLPS is not available + $sqlpsModule = Get-Module -Name 'SQLPS' -ListAvailable + if (-not $sqlpsModule) + { + Set-ItResult -Skipped -Because 'SQLPS module is not available on this system' + return + } + + { Import-SqlDscPreferredModule -Name 'SQLPS' -ErrorAction 'Stop' } | Should -Not -Throw + + $importedModule = Get-Module -Name 'SQLPS' + $importedModule | Should -Not -BeNullOrEmpty + $importedModule.Name | Should -Be 'SQLPS' + } + + It 'Should import SqlServer when specifically requested' { + # Skip if SqlServer is not available + $sqlServerModule = Get-Module -Name 'SqlServer' -ListAvailable + if (-not $sqlServerModule) + { + Set-ItResult -Skipped -Because 'SqlServer module is not available on this system' + return + } + + { Import-SqlDscPreferredModule -Name 'SqlServer' -ErrorAction 'Stop' } | Should -Not -Throw + + $importedModule = Get-Module -Name 'SqlServer' + $importedModule | Should -Not -BeNullOrEmpty + $importedModule.Name | Should -Be 'SqlServer' + } + } + + Context 'When SMODefaultModuleName environment variable is set' { + BeforeEach { + # Remove any SQL modules that might be loaded + Get-Module -Name @('SqlServer', 'SQLPS') | Remove-Module -Force -ErrorAction 'SilentlyContinue' + } + + AfterEach { + # Clean up environment variable after each test + Remove-Item -Path 'env:SMODefaultModuleName' -ErrorAction 'SilentlyContinue' + } + + It 'Should respect SMODefaultModuleName environment variable when set to SqlServer' { + # Skip if SqlServer is not available + $sqlServerModule = Get-Module -Name 'SqlServer' -ListAvailable + if (-not $sqlServerModule) + { + Set-ItResult -Skipped -Because 'SqlServer module is not available on this system' + return + } + + $env:SMODefaultModuleName = 'SqlServer' + + { Import-SqlDscPreferredModule -ErrorAction 'Stop' } | Should -Not -Throw + + $importedModule = Get-Module -Name @('SqlServer', 'SQLPS') | Select-Object -First 1 + $importedModule | Should -Not -BeNullOrEmpty + $importedModule.Name | Should -Be 'SqlServer' + } + } + + Context 'When handling module availability' { + BeforeEach { + # Remove any SQL modules that might be loaded + Get-Module -Name @('SqlServer', 'SQLPS') | Remove-Module -Force -ErrorAction 'SilentlyContinue' + } + + It 'Should handle the case when neither preferred module is available gracefully' { + # This test verifies error handling when no SQL modules are available + # We can't easily simulate this in CI where modules are installed, so we test with a non-existent module + { Import-SqlDscPreferredModule -Name 'NonExistentSqlModule' -ErrorAction 'Stop' } | Should -Throw + } + } +} + diff --git a/tests/Integration/Commands/README.md b/tests/Integration/Commands/README.md index d922aa952e..6b7ba03806 100644 --- a/tests/Integration/Commands/README.md +++ b/tests/Integration/Commands/README.md @@ -41,6 +41,7 @@ to each other. Dependencies are made to speed up the testing.** Command | Run order # | Depends on # | Use instance | Creates persistent objects --- | --- | --- | --- | --- Prerequisites | 0 | - | - | Sets up dependencies +Import-SqlDscPreferredModule | 0 | - | - | - Install-SqlDscServer | 1 | 0 (Prerequisites) | - | DSCSQLTEST instance Connect-SqlDscDatabaseEngine | 1 | 0 (Prerequisites) | DSCSQLTEST | - Assert-SqlDscLogin | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | -