tests/Unit/Public/Get-sqmDatabaseHealth.Tests.ps1
|
#Requires -Modules Pester <# .SYNOPSIS Unit Tests fuer Get-sqmDatabaseHealth dbatools-Abhaengigkeiten werden vollstaendig gemockt. #> BeforeAll { . "$PSScriptRoot\..\..\..\tests\TestHelpers.ps1" Import-sqmTestModule $script:TestDir = New-TempTestDirectory } AfterAll { if (Test-Path $script:TestDir) { Remove-Item $script:TestDir -Recurse -Force } if (Get-Module sqmSQLTool) { Remove-Module sqmSQLTool -Force } $env:MSSQLTOOLS_SKIP_AUTO_UPDATE = $null } Describe 'Get-sqmDatabaseHealth' { Context 'Parameter-Validierung' { It 'Funktion existiert und ist aufrufbar' { Get-Command Get-sqmDatabaseHealth | Should -Not -BeNullOrEmpty } It 'SqlInstance ist nicht mandatory (Default = Computername)' { $cmd = Get-Command Get-sqmDatabaseHealth $mandatory = $cmd.Parameters['SqlInstance'].Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] } | Select-Object -ExpandProperty Mandatory -First 1 $mandatory | Should -Be $false } It 'OutputPath Parameter existiert' { (Get-Command Get-sqmDatabaseHealth).Parameters.ContainsKey('OutputPath') | Should -Be $true } It 'WhatIf wird unterstuetzt' { (Get-Command Get-sqmDatabaseHealth).Parameters.ContainsKey('WhatIf') | Should -Be $true } It 'ExcludeDatabase Parameter existiert' { (Get-Command Get-sqmDatabaseHealth).Parameters.ContainsKey('ExcludeDatabase') | Should -Be $true } } Context 'Ausfuehrung mit gemockten dbatools' { BeforeAll { # dbatools-Funktionen mocken Mock -ModuleName sqmSQLTool Connect-DbaInstance { New-MockSqlInstance -Name 'TESTSERVER' } Mock -ModuleName sqmSQLTool Get-DbaDatabase { @( New-MockDatabase -Name 'TestDB1' -Status 'Normal' -RecoveryModel 'Full' New-MockDatabase -Name 'TestDB2' -Status 'Normal' -RecoveryModel 'Simple' New-MockDatabase -Name 'TestDB3' -Status 'Restoring' -RecoveryModel 'Full' ) } Mock -ModuleName sqmSQLTool Invoke-DbaQuery { @() } Mock -ModuleName sqmSQLTool Invoke-sqmLogging { } } It 'Laeuft ohne Fehler mit gemockten Daten' { { Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -WhatIf } | Should -Not -Throw } It 'Erstellt keine Dateien bei -WhatIf' { Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -WhatIf (Get-ChildItem $script:TestDir -File).Count | Should -Be 0 } } Context 'Backup-Ausschluss (sqm_BackupExclude)' { BeforeAll { Mock -ModuleName sqmSQLTool Connect-DbaInstance { New-MockSqlInstance -Name 'TESTSERVER' } Mock -ModuleName sqmSQLTool Get-DbaDatabase { @( New-MockDatabase -Name 'ExcludedDb' -Status 'Normal' -RecoveryModel 'Full' New-MockDatabase -Name 'NormalDb' -Status 'Normal' -RecoveryModel 'Full' ) } Mock -ModuleName sqmSQLTool Invoke-DbaQuery -ParameterFilter { $Query -like '*sys.objects*sqm_BackupExclude*' } { @(1) } Mock -ModuleName sqmSQLTool Invoke-DbaQuery -ParameterFilter { $Query -like 'SELECT DatabaseName, Reason FROM master.dbo.sqm_BackupExclude*' } { @([PSCustomObject]@{ DatabaseName = 'ExcludedDb'; Reason = 'Read-Replika, Backup laeuft auf Primary' }) } Mock -ModuleName sqmSQLTool Invoke-DbaQuery { @() } Mock -ModuleName sqmSQLTool Invoke-sqmLogging { } } It 'markiert die in sqm_BackupExclude gelistete Datenbank als ausgeschlossen' { $r = Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -NoOpen $rows = $r.DetailRows ($rows | Where-Object Database -eq 'ExcludedDb').ExcludedFromBackup | Should -Be $true ($rows | Where-Object Database -eq 'ExcludedDb').ExcludeReason | Should -Be 'Read-Replika, Backup laeuft auf Primary' } It 'laesst nicht gelistete Datenbanken unmarkiert' { $r = Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -NoOpen ($r.DetailRows | Where-Object Database -eq 'NormalDb').ExcludedFromBackup | Should -Be $false } It 'schreibt den Ausschluss-Hinweis und die Spalte in den HTML-Bericht' { $r = Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -NoOpen $html = Get-Content $r.HtmlFile -Raw $html | Should -Match 'Backup-Ausschluss' $html | Should -Match 'Ausgeschlossen' } } Context 'COPY_ONLY-Backups und Groessenformatierung' { BeforeAll { Mock -ModuleName sqmSQLTool Connect-DbaInstance { New-MockSqlInstance -Name 'TESTSERVER' } Mock -ModuleName sqmSQLTool Get-DbaDatabase { @( New-MockDatabase -Name 'CopyOnlyDb' -Status 'Normal' -RecoveryModel 'Full' -Size 12345.6 New-MockDatabase -Name 'RegularDb' -Status 'Normal' -RecoveryModel 'Full' -Size 512 ) } Mock -ModuleName sqmSQLTool Invoke-DbaQuery -ParameterFilter { $Query -like '*msdb.dbo.backupset*' } { @( # CopyOnlyDb hat NUR ein COPY_ONLY-Full [PSCustomObject]@{ database_name = 'CopyOnlyDb'; type = 'D'; is_copy_only = $true; LastBackup = [datetime]'2026-09-18 06:18:00' } # RegularDb hat beides - das regulaere Full gewinnt [PSCustomObject]@{ database_name = 'RegularDb'; type = 'D'; is_copy_only = $false; LastBackup = [datetime]'2026-09-17 22:00:00' } [PSCustomObject]@{ database_name = 'RegularDb'; type = 'D'; is_copy_only = $true; LastBackup = [datetime]'2026-09-18 06:18:00' } ) } Mock -ModuleName sqmSQLTool Invoke-DbaQuery { @() } Mock -ModuleName sqmSQLTool Invoke-sqmLogging { } } It 'meldet ein reines COPY_ONLY-Full nicht als "(keins)"' { $r = Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -NoOpen $row = $r.DetailRows | Where-Object Database -eq 'CopyOnlyDb' $row.LastFullBackup | Should -Be '(nur COPY_ONLY: 2026-09-18 06:18)' $row.LastCopyOnlyFull | Should -Be '2026-09-18 06:18' } It 'bevorzugt das regulaere Full, wenn beides vorhanden ist' { $r = Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -NoOpen $row = $r.DetailRows | Where-Object Database -eq 'RegularDb' $row.LastFullBackup | Should -Be '2026-09-17 22:00' $row.LastCopyOnlyFull | Should -Be '2026-09-18 06:18' } It 'schreibt die COPY_ONLY-Spalte und den Hinweis in die Berichte' { $r = Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -NoOpen $html = Get-Content $r.HtmlFile -Raw $html | Should -Match 'Nur COPY_ONLY' (Get-Content $r.TxtFile -Raw) | Should -Match 'Nur COPY_ONLY-Full vorhanden' } It 'gibt die Groesse rechtsbuendig mit Tausendertrennung aus' { $r = Get-sqmDatabaseHealth -SqlInstance 'TESTSERVER' -OutputPath $script:TestDir -NoOpen $html = Get-Content $r.HtmlFile -Raw $expected = '{0:N1}' -f 12345.6 # kulturabhaengig, genau wie im Bericht $html | Should -BeLike "*<td class='num'>$expected</td>*" $html | Should -Match "th class='num'>SizeMB" } } Context 'Fehlerbehandlung' { It 'Wirft Fehler bei nicht erreichbarer Instanz (kein Mock)' { { Get-sqmDatabaseHealth -SqlInstance 'NICHT_ERREICHBAR_99999' -OutputPath $script:TestDir -EnableException -ErrorAction Stop } | Should -Throw } } } |