From 1fabc48f6cdad1d5d4d4f265056b8ec27f6e9449 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 Aug 2025 07:57:03 +0000 Subject: [PATCH 01/15] Initial plan From cc00e283cb43bcfdb6a0562a924ddbf7bd68a690 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 Aug 2025 08:12:27 +0000 Subject: [PATCH 02/15] Add complete SqlDsc database public commands with tests Co-authored-by: johlju <7189721+johlju@users.noreply.github.com> --- CHANGELOG.md | 9 + source/Public/Get-SqlDscDatabase.ps1 | 103 ++++++++ source/Public/New-SqlDscDatabase.ps1 | 198 +++++++++++++++ source/Public/Remove-SqlDscDatabase.ps1 | 142 +++++++++++ source/Public/Set-SqlDscDatabase.ps1 | 228 ++++++++++++++++++ source/Public/Test-SqlDscDatabase.ps1 | 168 +++++++++++++ source/en-US/SqlServerDsc.strings.psd1 | 55 +++++ .../Get-SqlDscDatabase.Integration.Tests.ps1 | 106 ++++++++ .../New-SqlDscDatabase.Integration.Tests.ps1 | 120 +++++++++ .../Test-SqlDscDatabase.Integration.Tests.ps1 | 104 ++++++++ .../Unit/Public/Get-SqlDscDatabase.Tests.ps1 | 175 ++++++++++++++ .../Unit/Public/New-SqlDscDatabase.Tests.ps1 | 151 ++++++++++++ .../Public/Remove-SqlDscDatabase.Tests.ps1 | 155 ++++++++++++ .../Unit/Public/Set-SqlDscDatabase.Tests.ps1 | 191 +++++++++++++++ .../Unit/Public/Test-SqlDscDatabase.Tests.ps1 | 195 +++++++++++++++ 15 files changed, 2100 insertions(+) create mode 100644 source/Public/Get-SqlDscDatabase.ps1 create mode 100644 source/Public/New-SqlDscDatabase.ps1 create mode 100644 source/Public/Remove-SqlDscDatabase.ps1 create mode 100644 source/Public/Set-SqlDscDatabase.ps1 create mode 100644 source/Public/Test-SqlDscDatabase.ps1 create mode 100644 tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 create mode 100644 tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 create mode 100644 tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 create mode 100644 tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 create mode 100644 tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 create mode 100644 tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 create mode 100644 tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 create mode 100644 tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7265619754..43bc4f3cc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Supports pipeline input and provides detailed error messages with localization. - Uses `Test-SqlDscIsLogin` command for login validation following module patterns. - Added `Get-SqlDscLogin`, `Get-SqlDscRole`, `New-SqlDscLogin`, `New-SqlDscRole`, `Remove-SqlDscRole`, and `Remove-SqlDscLogin` commands for retrieving and managing SQL Server logins and roles with support for refresh, pipeline input, and ShouldProcess. +- Added new public commands for database management: + - `Get-SqlDscDatabase` - Get databases from a SQL Server Database Engine instance + - `New-SqlDscDatabase` - Create a new database with specified properties + - `Set-SqlDscDatabase` - Modify properties of an existing database + - `Remove-SqlDscDatabase` - Remove a database from SQL Server instance + - `Test-SqlDscDatabase` - Test if a database is in the desired state + - All commands support pipeline input with ServerObject and follow established patterns + - Database objects can also be used as pipeline input for Set and Remove operations + - Commands include comprehensive validation, localization, and ShouldProcess support ### Changed diff --git a/source/Public/Get-SqlDscDatabase.ps1 b/source/Public/Get-SqlDscDatabase.ps1 new file mode 100644 index 0000000000..6d447a3285 --- /dev/null +++ b/source/Public/Get-SqlDscDatabase.ps1 @@ -0,0 +1,103 @@ +<# + .SYNOPSIS + Get databases from a SQL Server Database Engine instance. + + .DESCRIPTION + This command gets one or more databases from a SQL Server Database Engine instance. + If no name is specified, all databases are returned. + + .PARAMETER ServerObject + Specifies current server connection object. + + .PARAMETER Name + Specifies the name of the database to get. If not specified, all + databases are returned. + + .PARAMETER Refresh + Specifies that the **ServerObject**'s databases should be refreshed before + trying to get the database object. This is helpful when databases could have been + modified outside of the **ServerObject**, for example through T-SQL. But + on instances with a large amount of databases it might be better to make + sure the **ServerObject** is recent enough. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Get-SqlDscDatabase + + Get all databases from the instance. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Get-SqlDscDatabase -Name 'MyDatabase' + + Get the database named **MyDatabase**. + + .OUTPUTS + `[Microsoft.SqlServer.Management.Smo.Database[]]` +#> +function Get-SqlDscDatabase +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType([Microsoft.SqlServer.Management.Smo.Database[]])] + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Server] + $ServerObject, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Refresh + ) + + process + { + if ($Refresh.IsPresent) + { + # Refresh the server object's databases collection + $ServerObject.Databases.Refresh() + } + + Write-Verbose -Message ($script:localizedData.Database_Get -f $ServerObject.InstanceName) + + $databaseObject = @() + + if ($PSBoundParameters.ContainsKey('Name')) + { + $databaseObject = $ServerObject.Databases[$Name] + + if (-not $databaseObject) + { + Write-Verbose -Message ($script:localizedData.Database_NotFound -f $Name) + + $missingDatabaseMessage = $script:localizedData.Database_NotFound -f $Name + + $writeErrorParameters = @{ + Message = $missingDatabaseMessage + Category = 'ObjectNotFound' + ErrorId = 'GSDD0001' # cspell: disable-line + TargetObject = $Name + } + + Write-Error @writeErrorParameters + } + else + { + Write-Verbose -Message ($script:localizedData.Database_Found -f $Name) + } + } + else + { + Write-Verbose -Message ($script:localizedData.Database_GetAll) + + $databaseObject = $ServerObject.Databases + } + + return [Microsoft.SqlServer.Management.Smo.Database[]] $databaseObject + } +} \ No newline at end of file diff --git a/source/Public/New-SqlDscDatabase.ps1 b/source/Public/New-SqlDscDatabase.ps1 new file mode 100644 index 0000000000..baf95bd94f --- /dev/null +++ b/source/Public/New-SqlDscDatabase.ps1 @@ -0,0 +1,198 @@ +<# + .SYNOPSIS + Creates a new database in a SQL Server Database Engine instance. + + .DESCRIPTION + This command creates a new database in a SQL Server Database Engine instance. + + .PARAMETER ServerObject + Specifies current server connection object. + + .PARAMETER Name + Specifies the name of the database to be created. + + .PARAMETER Collation + The name of the SQL collation to use for the new database. + Default value is server collation. + + .PARAMETER CompatibilityLevel + The version of the SQL compatibility level to use for the new database. + Default value is server version. + + .PARAMETER RecoveryModel + The recovery model to be used for the new database. + Default value is Full. + + .PARAMETER OwnerName + Specifies the name of the login that should be the owner of the database. + + .PARAMETER Force + Specifies that the database should be created without any confirmation. + + .PARAMETER Refresh + Specifies that the **ServerObject**'s databases should be refreshed before + creating the database object. This is helpful when databases could have been + modified outside of the **ServerObject**, for example through T-SQL. But + on instances with a large amount of databases it might be better to make + sure the **ServerObject** is recent enough. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | New-SqlDscDatabase -Name 'MyDatabase' + + Creates a new database named **MyDatabase**. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | New-SqlDscDatabase -Name 'MyDatabase' -Collation 'SQL_Latin1_General_Pref_CP850_CI_AS' -RecoveryModel 'Simple' -Force + + Creates a new database named **MyDatabase** with the specified collation and recovery model + without prompting for confirmation. + + .OUTPUTS + `[Microsoft.SqlServer.Management.Smo.Database]` +#> +function New-SqlDscDatabase +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType([Microsoft.SqlServer.Management.Smo.Database])] + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Server] + $ServerObject, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Name, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $Collation, + + [Parameter()] + [ValidateSet('Version80', 'Version90', 'Version100', 'Version110', 'Version120', 'Version130', 'Version140', 'Version150', 'Version160')] + [System.String] + $CompatibilityLevel, + + [Parameter()] + [ValidateSet('Simple', 'Full', 'BulkLogged')] + [System.String] + $RecoveryModel, + + [Parameter()] + [System.String] + $OwnerName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Refresh + ) + + process + { + if ($Refresh.IsPresent) + { + # Refresh the server object's databases collection + $ServerObject.Databases.Refresh() + } + + Write-Verbose -Message ($script:localizedData.Database_Create -f $Name, $ServerObject.InstanceName) + + # Check if the database already exists + if ($ServerObject.Databases[$Name]) + { + $errorMessage = $script:localizedData.Database_AlreadyExists -f $Name, $ServerObject.InstanceName + New-InvalidOperationException -Message $errorMessage + } + + # Validate compatibility level if specified + if ($PSBoundParameters.ContainsKey('CompatibilityLevel')) + { + $supportedCompatibilityLevels = @{ + 8 = @('Version80') + 9 = @('Version80', 'Version90') + 10 = @('Version80', 'Version90', 'Version100') + 11 = @('Version90', 'Version100', 'Version110') + 12 = @('Version100', 'Version110', 'Version120') + 13 = @('Version100', 'Version110', 'Version120', 'Version130') + 14 = @('Version100', 'Version110', 'Version120', 'Version130', 'Version140') + 15 = @('Version100', 'Version110', 'Version120', 'Version130', 'Version140', 'Version150') + 16 = @('Version100', 'Version110', 'Version120', 'Version130', 'Version140', 'Version150', 'Version160') + } + + if ($CompatibilityLevel -notin $supportedCompatibilityLevels.$($ServerObject.VersionMajor)) + { + $errorMessage = $script:localizedData.Database_InvalidCompatibilityLevel -f $CompatibilityLevel, $ServerObject.InstanceName + New-ObjectNotFoundException -Message $errorMessage + } + } + + # Validate collation if specified + if ($PSBoundParameters.ContainsKey('Collation')) + { + if ($Collation -notin $ServerObject.EnumCollations().Name) + { + $errorMessage = $script:localizedData.Database_InvalidCollation -f $Collation, $ServerObject.InstanceName + New-ObjectNotFoundException -Message $errorMessage + } + } + + $verboseDescriptionMessage = $script:localizedData.Database_Create_ShouldProcessVerboseDescription -f $Name, $ServerObject.InstanceName + $verboseWarningMessage = $script:localizedData.Database_Create_ShouldProcessVerboseWarning -f $Name + $captionMessage = $script:localizedData.Database_Create_ShouldProcessCaption + + if ($Force.IsPresent -or $PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + { + try + { + $sqlDatabaseObjectToCreate = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' -ArgumentList $ServerObject, $Name + + if ($PSBoundParameters.ContainsKey('RecoveryModel')) + { + $sqlDatabaseObjectToCreate.RecoveryModel = $RecoveryModel + } + + if ($PSBoundParameters.ContainsKey('Collation')) + { + $sqlDatabaseObjectToCreate.Collation = $Collation + } + + if ($PSBoundParameters.ContainsKey('CompatibilityLevel')) + { + $sqlDatabaseObjectToCreate.CompatibilityLevel = $CompatibilityLevel + } + + Write-Verbose -Message ($script:localizedData.Database_Creating -f $Name) + + $sqlDatabaseObjectToCreate.Create() + + <# + This must be run after the object is created because + the owner property is read-only and the method cannot + be call until the object has been created. + #> + if ($PSBoundParameters.ContainsKey('OwnerName')) + { + $sqlDatabaseObjectToCreate.SetOwner($OwnerName) + } + + Write-Verbose -Message ($script:localizedData.Database_Created -f $Name) + + return $sqlDatabaseObjectToCreate + } + catch + { + $errorMessage = $script:localizedData.Database_CreateFailed -f $Name, $ServerObject.InstanceName + New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ + } + } + } +} \ No newline at end of file diff --git a/source/Public/Remove-SqlDscDatabase.ps1 b/source/Public/Remove-SqlDscDatabase.ps1 new file mode 100644 index 0000000000..d0895d2786 --- /dev/null +++ b/source/Public/Remove-SqlDscDatabase.ps1 @@ -0,0 +1,142 @@ +<# + .SYNOPSIS + Removes a database from a SQL Server Database Engine instance. + + .DESCRIPTION + This command removes a database from a SQL Server Database Engine instance. + + .PARAMETER ServerObject + Specifies current server connection object. + + .PARAMETER DatabaseObject + Specifies a database object to remove. + + .PARAMETER Name + Specifies the name of the database to be removed. + + .PARAMETER Force + Specifies that the database should be removed without any confirmation. + + .PARAMETER Refresh + Specifies that the **ServerObject**'s databases should be refreshed before + trying to remove the database object. This is helpful when databases could have been + modified outside of the **ServerObject**, for example through T-SQL. But + on instances with a large amount of databases it might be better to make + sure the **ServerObject** is recent enough, or pass in **DatabaseObject**. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $databaseObject = $serverObject | Get-SqlDscDatabase -Name 'MyDatabase' + $databaseObject | Remove-SqlDscDatabase + + Removes the database named **MyDatabase**. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Remove-SqlDscDatabase -Name 'MyDatabase' + + Removes the database named **MyDatabase**. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Remove-SqlDscDatabase -Name 'MyDatabase' -Force + + Removes the database named **MyDatabase** without prompting for confirmation. + + .OUTPUTS + None. +#> +function Remove-SqlDscDatabase +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType()] + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] + param + ( + [Parameter(ParameterSetName = 'ServerObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Server] + $ServerObject, + + [Parameter(ParameterSetName = 'DatabaseObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Database] + $DatabaseObject, + + [Parameter(ParameterSetName = 'ServerObject', Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Name, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force, + + [Parameter(ParameterSetName = 'ServerObject')] + [System.Management.Automation.SwitchParameter] + $Refresh + ) + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ServerObject') + { + if ($Refresh.IsPresent) + { + # Refresh the server object's databases collection + $ServerObject.Databases.Refresh() + } + + Write-Verbose -Message ($script:localizedData.Database_Remove -f $Name, $ServerObject.InstanceName) + + # Check if the database is a system database (cannot be dropped) + $systemDatabases = @('master', 'model', 'msdb', 'tempdb') + if ($Name -in $systemDatabases) + { + $errorMessage = $script:localizedData.Database_CannotRemoveSystem -f $Name + New-InvalidOperationException -Message $errorMessage + } + + # Get the database object + $DatabaseObject = $ServerObject.Databases[$Name] + + if (-not $DatabaseObject) + { + $errorMessage = $script:localizedData.Database_NotFound -f $Name + New-InvalidOperationException -Message $errorMessage + } + } + else + { + $Name = $DatabaseObject.Name + Write-Verbose -Message ($script:localizedData.Database_Remove -f $Name, $DatabaseObject.Parent.InstanceName) + + # Check if the database is a system database (cannot be dropped) + $systemDatabases = @('master', 'model', 'msdb', 'tempdb') + if ($Name -in $systemDatabases) + { + $errorMessage = $script:localizedData.Database_CannotRemoveSystem -f $Name + New-InvalidOperationException -Message $errorMessage + } + } + + $verboseDescriptionMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseDescription -f $Name, $DatabaseObject.Parent.InstanceName + $verboseWarningMessage = $script:localizedData.Database_Remove_ShouldProcessVerboseWarning -f $Name + $captionMessage = $script:localizedData.Database_Remove_ShouldProcessCaption + + if ($Force.IsPresent -or $PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + { + try + { + Write-Verbose -Message ($script:localizedData.Database_Removing -f $Name) + + $DatabaseObject.Drop() + + Write-Verbose -Message ($script:localizedData.Database_Removed -f $Name) + } + catch + { + $errorMessage = $script:localizedData.Database_RemoveFailed -f $Name, $DatabaseObject.Parent.InstanceName + New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ + } + } + } +} \ No newline at end of file diff --git a/source/Public/Set-SqlDscDatabase.ps1 b/source/Public/Set-SqlDscDatabase.ps1 new file mode 100644 index 0000000000..3aa42100d0 --- /dev/null +++ b/source/Public/Set-SqlDscDatabase.ps1 @@ -0,0 +1,228 @@ +<# + .SYNOPSIS + Sets properties of a database in a SQL Server Database Engine instance. + + .DESCRIPTION + This command sets properties of a database in a SQL Server Database Engine instance. + + .PARAMETER ServerObject + Specifies current server connection object. + + .PARAMETER DatabaseObject + Specifies a database object to modify. + + .PARAMETER Name + Specifies the name of the database to be modified. + + .PARAMETER Collation + The name of the SQL collation to set for the database. + + .PARAMETER CompatibilityLevel + The version of the SQL compatibility level to set for the database. + + .PARAMETER RecoveryModel + The recovery model to be set for the database. + + .PARAMETER OwnerName + Specifies the name of the login that should be the owner of the database. + + .PARAMETER Force + Specifies that the database should be modified without any confirmation. + + .PARAMETER Refresh + Specifies that the **ServerObject**'s databases should be refreshed before + modifying the database object. This is helpful when databases could have been + modified outside of the **ServerObject**, for example through T-SQL. But + on instances with a large amount of databases it might be better to make + sure the **ServerObject** is recent enough, or pass in **DatabaseObject**. + + .PARAMETER PassThru + Specifies that the database object should be returned after modification. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $databaseObject = $serverObject | Get-SqlDscDatabase -Name 'MyDatabase' + $databaseObject | Set-SqlDscDatabase -RecoveryModel 'Simple' + + Sets the recovery model of the database named **MyDatabase** to **Simple**. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Set-SqlDscDatabase -Name 'MyDatabase' -OwnerName 'sa' -Force + + Sets the owner of the database named **MyDatabase** to **sa** without prompting for confirmation. + + .OUTPUTS + None. But when **PassThru** is specified the output is `[Microsoft.SqlServer.Management.Smo.Database]`. +#> +function Set-SqlDscDatabase +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType()] + [OutputType([Microsoft.SqlServer.Management.Smo.Database])] + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] + param + ( + [Parameter(ParameterSetName = 'ServerObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Server] + $ServerObject, + + [Parameter(ParameterSetName = 'DatabaseObject', Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Database] + $DatabaseObject, + + [Parameter(ParameterSetName = 'ServerObject', Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Name, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $Collation, + + [Parameter()] + [ValidateSet('Version80', 'Version90', 'Version100', 'Version110', 'Version120', 'Version130', 'Version140', 'Version150', 'Version160')] + [System.String] + $CompatibilityLevel, + + [Parameter()] + [ValidateSet('Simple', 'Full', 'BulkLogged')] + [System.String] + $RecoveryModel, + + [Parameter()] + [System.String] + $OwnerName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force, + + [Parameter(ParameterSetName = 'ServerObject')] + [System.Management.Automation.SwitchParameter] + $Refresh, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru + ) + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ServerObject') + { + if ($Refresh.IsPresent) + { + # Refresh the server object's databases collection + $ServerObject.Databases.Refresh() + } + + Write-Verbose -Message ($script:localizedData.Database_Set -f $Name, $ServerObject.InstanceName) + + # Get the database object + $DatabaseObject = $ServerObject.Databases[$Name] + + if (-not $DatabaseObject) + { + $errorMessage = $script:localizedData.Database_NotFound -f $Name + New-InvalidOperationException -Message $errorMessage + } + } + else + { + $Name = $DatabaseObject.Name + $ServerObject = $DatabaseObject.Parent + Write-Verbose -Message ($script:localizedData.Database_Set -f $Name, $ServerObject.InstanceName) + } + + # Validate compatibility level if specified + if ($PSBoundParameters.ContainsKey('CompatibilityLevel')) + { + $supportedCompatibilityLevels = @{ + 8 = @('Version80') + 9 = @('Version80', 'Version90') + 10 = @('Version80', 'Version90', 'Version100') + 11 = @('Version90', 'Version100', 'Version110') + 12 = @('Version100', 'Version110', 'Version120') + 13 = @('Version100', 'Version110', 'Version120', 'Version130') + 14 = @('Version100', 'Version110', 'Version120', 'Version130', 'Version140') + 15 = @('Version100', 'Version110', 'Version120', 'Version130', 'Version140', 'Version150') + 16 = @('Version100', 'Version110', 'Version120', 'Version130', 'Version140', 'Version150', 'Version160') + } + + if ($CompatibilityLevel -notin $supportedCompatibilityLevels.$($ServerObject.VersionMajor)) + { + $errorMessage = $script:localizedData.Database_InvalidCompatibilityLevel -f $CompatibilityLevel, $ServerObject.InstanceName + New-ObjectNotFoundException -Message $errorMessage + } + } + + # Validate collation if specified + if ($PSBoundParameters.ContainsKey('Collation')) + { + if ($Collation -notin $ServerObject.EnumCollations().Name) + { + $errorMessage = $script:localizedData.Database_InvalidCollation -f $Collation, $ServerObject.InstanceName + New-ObjectNotFoundException -Message $errorMessage + } + } + + $verboseDescriptionMessage = $script:localizedData.Database_Set_ShouldProcessVerboseDescription -f $Name, $ServerObject.InstanceName + $verboseWarningMessage = $script:localizedData.Database_Set_ShouldProcessVerboseWarning -f $Name + $captionMessage = $script:localizedData.Database_Set_ShouldProcessCaption + + if ($Force.IsPresent -or $PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + { + try + { + $wasUpdate = $false + + if ($PSBoundParameters.ContainsKey('Collation')) + { + Write-Verbose -Message ($script:localizedData.Database_UpdatingCollation -f $Collation) + $DatabaseObject.Collation = $Collation + $wasUpdate = $true + } + + if ($PSBoundParameters.ContainsKey('CompatibilityLevel')) + { + Write-Verbose -Message ($script:localizedData.Database_UpdatingCompatibilityLevel -f $CompatibilityLevel) + $DatabaseObject.CompatibilityLevel = $CompatibilityLevel + $wasUpdate = $true + } + + if ($PSBoundParameters.ContainsKey('RecoveryModel')) + { + Write-Verbose -Message ($script:localizedData.Database_UpdatingRecoveryModel -f $RecoveryModel) + $DatabaseObject.RecoveryModel = $RecoveryModel + $wasUpdate = $true + } + + if ($PSBoundParameters.ContainsKey('OwnerName')) + { + Write-Verbose -Message ($script:localizedData.Database_UpdatingOwner -f $OwnerName) + $DatabaseObject.SetOwner($OwnerName) + $wasUpdate = $true + } + + if ($wasUpdate) + { + Write-Verbose -Message ($script:localizedData.Database_Updating -f $Name) + $DatabaseObject.Alter() + Write-Verbose -Message ($script:localizedData.Database_Updated -f $Name) + } + + if ($PassThru.IsPresent) + { + return $DatabaseObject + } + } + catch + { + $errorMessage = $script:localizedData.Database_SetFailed -f $Name, $ServerObject.InstanceName + New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ + } + } + } +} \ No newline at end of file diff --git a/source/Public/Test-SqlDscDatabase.ps1 b/source/Public/Test-SqlDscDatabase.ps1 new file mode 100644 index 0000000000..5c973ae163 --- /dev/null +++ b/source/Public/Test-SqlDscDatabase.ps1 @@ -0,0 +1,168 @@ +<# + .SYNOPSIS + Tests if a database on a SQL Server Database Engine instance is in the desired state. + + .DESCRIPTION + This command tests if a database on a SQL Server Database Engine instance is in the desired state. + + .PARAMETER ServerObject + Specifies current server connection object. + + .PARAMETER Name + Specifies the name of the database to test. + + .PARAMETER Ensure + When set to 'Present', the database must exist. + When set to 'Absent', the database must not exist. + + .PARAMETER Collation + The name of the SQL collation that the database should have. + + .PARAMETER CompatibilityLevel + The version of the SQL compatibility level that the database should have. + + .PARAMETER RecoveryModel + The recovery model that the database should have. + + .PARAMETER OwnerName + Specifies the name of the login that should be the owner of the database. + + .PARAMETER Refresh + Specifies that the **ServerObject**'s databases should be refreshed before + testing the database state. This is helpful when databases could have been + modified outside of the **ServerObject**, for example through T-SQL. But + on instances with a large amount of databases it might be better to make + sure the **ServerObject** is recent enough. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Test-SqlDscDatabase -Name 'MyDatabase' -Ensure 'Present' + + Tests if the database named **MyDatabase** exists. + + .EXAMPLE + $serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance' + $serverObject | Test-SqlDscDatabase -Name 'MyDatabase' -Ensure 'Present' -RecoveryModel 'Simple' -OwnerName 'sa' + + Tests if the database named **MyDatabase** exists and has the specified recovery model and owner. + + .OUTPUTS + `[System.Boolean]` +#> +function Test-SqlDscDatabase +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')] + [OutputType([System.Boolean])] + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Microsoft.SqlServer.Management.Smo.Server] + $ServerObject, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.String] + $Name, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [ValidateNotNullOrEmpty()] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [ValidateNotNullOrEmpty()] + [System.String] + $Collation, + + [Parameter()] + [ValidateSet('Version80', 'Version90', 'Version100', 'Version110', 'Version120', 'Version130', 'Version140', 'Version150', 'Version160')] + [System.String] + $CompatibilityLevel, + + [Parameter()] + [ValidateSet('Simple', 'Full', 'BulkLogged')] + [System.String] + $RecoveryModel, + + [Parameter()] + [System.String] + $OwnerName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Refresh + ) + + process + { + if ($Refresh.IsPresent) + { + # Refresh the server object's databases collection + $ServerObject.Databases.Refresh() + } + + Write-Verbose -Message ($script:localizedData.Database_Test -f $Name, $ServerObject.InstanceName) + + $isDatabaseInDesiredState = $true + + # Check database exists + $sqlDatabaseObject = $ServerObject.Databases[$Name] + + switch ($Ensure) + { + 'Absent' + { + if ($sqlDatabaseObject) + { + Write-Verbose -Message ($script:localizedData.Database_NotInDesiredStateAbsent -f $Name) + $isDatabaseInDesiredState = $false + } + else + { + Write-Verbose -Message ($script:localizedData.Database_InDesiredStateAbsent -f $Name) + } + } + + 'Present' + { + if (-not $sqlDatabaseObject) + { + Write-Verbose -Message ($script:localizedData.Database_NotInDesiredStatePresent -f $Name) + $isDatabaseInDesiredState = $false + } + else + { + Write-Verbose -Message ($script:localizedData.Database_InDesiredStatePresent -f $Name) + + if ($PSBoundParameters.ContainsKey('Collation') -and $sqlDatabaseObject.Collation -ne $Collation) + { + Write-Verbose -Message ($script:localizedData.Database_CollationWrong -f $Name, $sqlDatabaseObject.Collation, $Collation) + $isDatabaseInDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('CompatibilityLevel') -and $sqlDatabaseObject.CompatibilityLevel -ne $CompatibilityLevel) + { + Write-Verbose -Message ($script:localizedData.Database_CompatibilityLevelWrong -f $Name, $sqlDatabaseObject.CompatibilityLevel, $CompatibilityLevel) + $isDatabaseInDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('RecoveryModel') -and $sqlDatabaseObject.RecoveryModel -ne $RecoveryModel) + { + Write-Verbose -Message ($script:localizedData.Database_RecoveryModelWrong -f $Name, $sqlDatabaseObject.RecoveryModel, $RecoveryModel) + $isDatabaseInDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('OwnerName') -and $sqlDatabaseObject.Owner -ne $OwnerName) + { + Write-Verbose -Message ($script:localizedData.Database_OwnerNameWrong -f $Name, $sqlDatabaseObject.Owner, $OwnerName) + $isDatabaseInDesiredState = $false + } + } + } + } + + return $isDatabaseInDesiredState + } +} \ No newline at end of file diff --git a/source/en-US/SqlServerDsc.strings.psd1 b/source/en-US/SqlServerDsc.strings.psd1 index 92edba1917..8489cc5658 100644 --- a/source/en-US/SqlServerDsc.strings.psd1 +++ b/source/en-US/SqlServerDsc.strings.psd1 @@ -276,4 +276,59 @@ ConvertFrom-StringData @' Login_Add_ShouldProcessCaption = Create login on instance Login_Add_LoginCreated = Successfully created login '{0}' on the instance '{1}'. Login_Add_LoginAlreadyExists = The login '{0}' already exists on the instance '{1}'. + + ## Get-SqlDscDatabase + Database_Get = Getting databases from instance '{0}'. + Database_GetAll = Getting all databases. + Database_Found = Found database '{0}'. + Database_NotFound = Database '{0}' was not found. + + ## New-SqlDscDatabase + Database_Create = Creating database '{0}' on instance '{1}'. + Database_Creating = Creating database '{0}'. + Database_Created = Database '{0}' was created successfully. + Database_CreateFailed = Failed to create database '{0}' on instance '{1}'. + Database_AlreadyExists = Database '{0}' already exists on instance '{1}'. + Database_InvalidCompatibilityLevel = The specified compatibility level '{0}' is not a valid compatibility level for the instance '{1}'. + Database_InvalidCollation = The specified collation '{0}' is not a valid collation for the instance '{1}'. + Database_Create_ShouldProcessVerboseDescription = Creating the database '{0}' on the instance '{1}'. + Database_Create_ShouldProcessVerboseWarning = Are you sure you want to create the database '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + Database_Create_ShouldProcessCaption = Create database on instance + + ## Set-SqlDscDatabase + Database_Set = Setting properties of database '{0}' on instance '{1}'. + Database_Updating = Updating database '{0}'. + Database_Updated = Database '{0}' was updated successfully. + Database_SetFailed = Failed to set properties of database '{0}' on instance '{1}'. + Database_UpdatingCollation = Changing the database collation to '{0}'. + Database_UpdatingCompatibilityLevel = Changing the database compatibility level to '{0}'. + Database_UpdatingRecoveryModel = Changing the database recovery model to '{0}'. + Database_UpdatingOwner = Changing the database owner to '{0}'. + Database_Set_ShouldProcessVerboseDescription = Setting properties of the database '{0}' on the instance '{1}'. + Database_Set_ShouldProcessVerboseWarning = Are you sure you want to modify the database '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + Database_Set_ShouldProcessCaption = Set database properties on instance + + ## Remove-SqlDscDatabase + Database_Remove = Removing database '{0}' from instance '{1}'. + Database_Removing = Removing database '{0}'. + Database_Removed = Database '{0}' was removed successfully. + Database_RemoveFailed = Failed to remove database '{0}' from instance '{1}'. + Database_CannotRemoveSystem = Cannot remove system database '{0}'. + Database_Remove_ShouldProcessVerboseDescription = Removing the database '{0}' from the instance '{1}'. + Database_Remove_ShouldProcessVerboseWarning = Are you sure you want to remove the database '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + Database_Remove_ShouldProcessCaption = Remove database from instance + + ## Test-SqlDscDatabase + Database_Test = Testing the state of database '{0}' on instance '{1}'. + Database_InDesiredStatePresent = Database '{0}' is present and in desired state. + Database_InDesiredStateAbsent = Database '{0}' is absent as expected. + Database_NotInDesiredStatePresent = Expected the database '{0}' to be present, but it was absent. + Database_NotInDesiredStateAbsent = Expected the database '{0}' to be absent, but it was present. + Database_CollationWrong = The database '{0}' exists and has the collation '{1}', but expected it to have the collation '{2}'. + Database_CompatibilityLevelWrong = The database '{0}' exists and has the compatibility level '{1}', but expected it to have the compatibility level '{2}'. + Database_RecoveryModelWrong = The database '{0}' exists and has the recovery model '{1}', but expected it to have the recovery model '{2}'. + Database_OwnerNameWrong = The database '{0}' exists and has the owner '{1}', but expected it to have the owner '{2}'. '@ diff --git a/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 new file mode 100644 index 0000000000..d5681a1915 --- /dev/null +++ b/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 @@ -0,0 +1,106 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + Import-Module -Name $script:dscModuleName +} + +Describe 'Get-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + + $script:mockInstanceName = 'DSCSQLTEST' + $script:mockComputerName = Get-ComputerName + + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force + + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) + + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + } + + AfterAll { + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + + # Stop the named instance SQL Server service to save memory on the build worker. + Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + } + + Context 'When getting all SQL Server databases' { + It 'Should return an array of Database objects' { + $result = Get-SqlDscDatabase -ServerObject $script:serverObject + + <# + Casting to array to ensure we get the count on Windows PowerShell + when there is only one database. + #> + @($result).Count | Should -BeGreaterOrEqual 1 + @($result)[0] | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Database' + } + + It 'Should return system databases including master' { + $result = Get-SqlDscDatabase -ServerObject $script:serverObject + + $result.Name | Should -Contain 'master' + $result.Name | Should -Contain 'model' + $result.Name | Should -Contain 'msdb' + $result.Name | Should -Contain 'tempdb' + } + } + + Context 'When getting a specific SQL Server database' { + It 'Should return the specified database when it exists (system database)' { + $result = Get-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be 'master' + $result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Database' + } + + It 'Should throw error when getting a non-existent database' { + { Get-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -ErrorAction 'Stop' } | + Should -Throw -ExpectedMessage "*not found*" + } + + It 'Should return nothing when getting a non-existent database with SilentlyContinue' { + $result = Get-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -ErrorAction 'SilentlyContinue' + + $result | Should -BeNullOrEmpty + } + } + + Context 'When using the Refresh parameter' { + It 'Should refresh the database collection and return databases' { + $result = Get-SqlDscDatabase -ServerObject $script:serverObject -Refresh + + @($result).Count | Should -BeGreaterOrEqual 1 + $result.Name | Should -Contain 'master' + } + } +} \ No newline at end of file diff --git a/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 new file mode 100644 index 0000000000..ea756c166f --- /dev/null +++ b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 @@ -0,0 +1,120 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + Import-Module -Name $script:dscModuleName +} + +Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + + $script:mockInstanceName = 'DSCSQLTEST' + $script:mockComputerName = Get-ComputerName + + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force + + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) + + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + + # Test database names + $script:testDatabaseName = 'SqlDscTestDatabase_' + (Get-Random) + $script:testDatabaseNameWithProperties = 'SqlDscTestDatabaseWithProps_' + (Get-Random) + } + + AfterAll { + # Clean up test databases + $testDatabasesToRemove = @($script:testDatabaseName, $script:testDatabaseNameWithProperties) + + foreach ($dbName in $testDatabasesToRemove) { + $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $dbName -ErrorAction 'SilentlyContinue' + if ($existingDb) { + Remove-SqlDscDatabase -DatabaseObject $existingDb -Force + } + } + + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + + # Stop the named instance SQL Server service to save memory on the build worker. + Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + } + + Context 'When creating a new database' { + It 'Should create a database successfully with minimal parameters' { + $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be $script:testDatabaseName + $result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Database' + + # Verify the database exists + $createdDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $createdDb | Should -Not -BeNullOrEmpty + } + + It 'Should create a database with specified properties' { + $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameWithProperties -RecoveryModel 'Simple' -Force + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be $script:testDatabaseNameWithProperties + $result.RecoveryModel | Should -Be 'Simple' + + # Verify the database exists with correct properties + $createdDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameWithProperties + $createdDb | Should -Not -BeNullOrEmpty + $createdDb.RecoveryModel | Should -Be 'Simple' + } + + It 'Should throw error when trying to create a database that already exists' { + { New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force } | + Should -Throw -ExpectedMessage "*already exists*" + } + } + + Context 'When using the Refresh parameter' { + It 'Should refresh the database collection before creating' { + $uniqueName = 'SqlDscTestRefresh_' + (Get-Random) + + try { + $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $uniqueName -Refresh -Force + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be $uniqueName + } + finally { + # Clean up + $dbToRemove = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $uniqueName -ErrorAction 'SilentlyContinue' + if ($dbToRemove) { + Remove-SqlDscDatabase -DatabaseObject $dbToRemove -Force + } + } + } + } +} \ No newline at end of file diff --git a/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 new file mode 100644 index 0000000000..a3385a4e0f --- /dev/null +++ b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 @@ -0,0 +1,104 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + Import-Module -Name $script:dscModuleName +} + +Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + + $script:mockInstanceName = 'DSCSQLTEST' + $script:mockComputerName = Get-ComputerName + + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force + + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) + + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + } + + AfterAll { + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + + # Stop the named instance SQL Server service to save memory on the build worker. + Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + } + + Context 'When testing database presence' { + It 'Should return true when system database exists and Ensure is Present' { + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' + + $result | Should -BeTrue + } + + It 'Should return false when non-existent database is tested with Ensure Present' { + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Ensure 'Present' + + $result | Should -BeFalse + } + + It 'Should return false when system database exists and Ensure is Absent' { + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Absent' + + $result | Should -BeFalse + } + + It 'Should return true when non-existent database is tested with Ensure Absent' { + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Ensure 'Absent' + + $result | Should -BeTrue + } + } + + Context 'When testing database properties' { + It 'Should return true when testing master database with correct recovery model' { + # Master database typically has Simple recovery model + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -RecoveryModel 'Simple' + + $result | Should -BeTrue + } + + It 'Should return false when testing master database with incorrect recovery model' { + # Master database typically has Simple recovery model, so Full should return false + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -RecoveryModel 'Full' + + $result | Should -BeFalse + } + } + + Context 'When using the Refresh parameter' { + It 'Should refresh the database collection and test database presence' { + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -Refresh + + $result | Should -BeTrue + } + } +} \ No newline at end of file diff --git a/tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 new file mode 100644 index 0000000000..67187f7e89 --- /dev/null +++ b/tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 @@ -0,0 +1,175 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +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:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Get-SqlDscDatabase' -Tag 'Public' { + Context 'When getting all databases' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + $databaseCollection = @( + (New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' -ArgumentList @($mockServerObject, 'master')), + (New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' -ArgumentList @($mockServerObject, 'TestDatabase')) + ) + return $databaseCollection | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + # Mock implementation + } -PassThru -Force + } -Force + } + + It 'Should return all databases when no Name parameter is specified' { + Mock -CommandName 'Write-Verbose' + + $result = Get-SqlDscDatabase -ServerObject $mockServerObject + + $result | Should -HaveCount 2 + $result[0].Name | Should -Be 'master' + $result[1].Name | Should -Be 'TestDatabase' + } + + It 'Should call Refresh when Refresh parameter is specified' { + Mock -CommandName 'Write-Verbose' + + $script:refreshCalled = $false + $mockServerObjectWithRefresh = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObjectWithRefresh | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObjectWithRefresh | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + $databaseCollection = @( + (New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' -ArgumentList @($mockServerObjectWithRefresh, 'master')) + ) + return $databaseCollection | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + $script:refreshCalled = $true + } -PassThru -Force + } -Force + + $result = Get-SqlDscDatabase -ServerObject $mockServerObjectWithRefresh -Refresh + + $result | Should -HaveCount 1 + $script:refreshCalled | Should -BeTrue + } + } + + Context 'When getting a specific database' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'master' = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' -ArgumentList @($mockServerObject, 'master') + 'TestDatabase' = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' -ArgumentList @($mockServerObject, 'TestDatabase') + } | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + # Mock implementation + } -PassThru -Force + } -Force + } + + It 'Should return the specified database when it exists' { + Mock -CommandName 'Write-Verbose' + + $result = Get-SqlDscDatabase -ServerObject $mockServerObject -Name 'master' + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be 'master' + } + + It 'Should throw the correct error when the specified database does not exist' { + Mock -CommandName 'Write-Verbose' + + # Test the exact error message first + $expectedMessage = 'Database ''NonExistentDatabase'' was not found.' + + { Get-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -ErrorAction 'Stop' } | + Should -Throw -ExpectedMessage $expectedMessage + } + + It 'Should return empty result when ignoring the error' { + Mock -CommandName 'Write-Verbose' + + $result = Get-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -ErrorAction 'SilentlyContinue' + + $result | Should -BeNullOrEmpty + } + } + + Context 'Parameter validation' { + It 'Should have the correct parameters in parameter set __AllParameterSets' -ForEach @( + @{ + ExpectedParameterSetName = '__AllParameterSets' + ExpectedParameters = '[-ServerObject] [[-Name] ] [-Refresh] []' + } + ) { + $result = (Get-Command -Name 'Get-SqlDscDatabase').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + + It 'Should have ServerObject as a mandatory parameter' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscDatabase').Parameters['ServerObject'] + $parameterInfo.Attributes.Mandatory | Should -BeTrue + } + + It 'Should have Name as a non-mandatory parameter' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscDatabase').Parameters['Name'] + $parameterInfo.Attributes.Mandatory | Should -BeFalse + } + + It 'Should have Refresh as a non-mandatory parameter' { + $parameterInfo = (Get-Command -Name 'Get-SqlDscDatabase').Parameters['Refresh'] + $parameterInfo.Attributes.Mandatory | Should -BeFalse + } + } +} \ No newline at end of file diff --git a/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 new file mode 100644 index 0000000000..40882af06b --- /dev/null +++ b/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 @@ -0,0 +1,151 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +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:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'New-SqlDscDatabase' -Tag 'Public' { + Context 'When creating a new database' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{} | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + # Mock implementation + } -PassThru -Force + } -Force + $mockServerObject | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' }, + @{ Name = 'SQL_Latin1_General_Pref_CP850_CI_AS' } + ) + } -Force + + Mock -CommandName 'New-Object' -ParameterFilter { $TypeName -eq 'Microsoft.SqlServer.Management.Smo.Database' } -MockWith { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value $ArgumentList[1] -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'RecoveryModel' -Value $null -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Collation' -Value $null -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'CompatibilityLevel' -Value $null -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'Create' -Value { + # Mock implementation + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetOwner' -Value { + param($OwnerName) + # Mock implementation + } -Force + return $mockDatabaseObject + } + } + + It 'Should create a database successfully with minimal parameters' { + Mock -CommandName 'Write-Verbose' + + $result = New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Force + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be 'TestDatabase' + Should -Invoke -CommandName 'New-Object' -ParameterFilter { $TypeName -eq 'Microsoft.SqlServer.Management.Smo.Database' } -Exactly -Times 1 + } + + It 'Should create a database with specified properties' { + Mock -CommandName 'Write-Verbose' + + $result = New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase2' -Collation 'SQL_Latin1_General_CP1_CI_AS' -RecoveryModel 'Simple' -CompatibilityLevel 'Version150' -OwnerName 'sa' -Force + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be 'TestDatabase2' + $result.RecoveryModel | Should -Be 'Simple' + $result.Collation | Should -Be 'SQL_Latin1_General_CP1_CI_AS' + $result.CompatibilityLevel | Should -Be 'Version150' + } + + It 'Should throw error when database already exists' { + $mockServerObjectWithExistingDb = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObjectWithExistingDb | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObjectWithExistingDb | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'ExistingDatabase' = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + } + } -Force + + { New-SqlDscDatabase -ServerObject $mockServerObjectWithExistingDb -Name 'ExistingDatabase' -Force } | + Should -Throw -ExpectedMessage '*already exists*' + } + } + + Context 'Parameter validation' { + It 'Should have the correct parameters in parameter set __AllParameterSets' -ForEach @( + @{ + ExpectedParameterSetName = '__AllParameterSets' + ExpectedParameters = '[-ServerObject] [-Name] [[-Collation] ] [[-CompatibilityLevel] ] [[-RecoveryModel] ] [[-OwnerName] ] [-Force] [-Refresh] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'New-SqlDscDatabase').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + + It 'Should have ServerObject as a mandatory parameter' { + $parameterInfo = (Get-Command -Name 'New-SqlDscDatabase').Parameters['ServerObject'] + $parameterInfo.Attributes.Mandatory | Should -BeTrue + } + + It 'Should have Name as a mandatory parameter' { + $parameterInfo = (Get-Command -Name 'New-SqlDscDatabase').Parameters['Name'] + $parameterInfo.Attributes.Mandatory | Should -BeTrue + } + } +} \ No newline at end of file diff --git a/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 new file mode 100644 index 0000000000..6459b77902 --- /dev/null +++ b/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 @@ -0,0 +1,155 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +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:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Remove-SqlDscDatabase' -Tag 'Public' { + Context 'When removing a database using ServerObject and Name' { + BeforeAll { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + return $mockParent + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'Drop' -Value { + # Mock implementation + } -Force + + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockDatabaseObject + 'master' = $mockDatabaseObject + } | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + # Mock implementation + } -PassThru -Force + } -Force + } + + It 'Should remove database successfully' { + Mock -CommandName 'Write-Verbose' + + { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Force } | Should -Not -Throw + } + + It 'Should throw error when database does not exist' { + Mock -CommandName 'Write-Verbose' + + { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Force } | + Should -Throw -ExpectedMessage '*not found*' + } + + It 'Should throw error when trying to remove system database' { + Mock -CommandName 'Write-Verbose' + + { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'master' -Force } | + Should -Throw -ExpectedMessage '*Cannot remove system database*' + } + } + + Context 'When removing a database using DatabaseObject' { + BeforeAll { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + return $mockParent + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'Drop' -Value { + # Mock implementation + } -Force + } + + It 'Should remove database successfully using database object' { + Mock -CommandName 'Write-Verbose' + + { Remove-SqlDscDatabase -DatabaseObject $mockDatabaseObject -Force } | Should -Not -Throw + } + } + + Context 'Parameter validation' { + It 'Should have the correct parameters in parameter set ServerObject' -ForEach @( + @{ + ExpectedParameterSetName = 'ServerObject' + ExpectedParameters = '-ServerObject -Name [-Force] [-Refresh] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Remove-SqlDscDatabase').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + + It 'Should have the correct parameters in parameter set DatabaseObject' -ForEach @( + @{ + ExpectedParameterSetName = 'DatabaseObject' + ExpectedParameters = '-DatabaseObject [-Force] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Remove-SqlDscDatabase').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + } +} \ No newline at end of file diff --git a/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 new file mode 100644 index 0000000000..6aeabf12c6 --- /dev/null +++ b/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 @@ -0,0 +1,191 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +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:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Set-SqlDscDatabase' -Tag 'Public' { + Context 'When modifying a database using ServerObject and Name' { + BeforeAll { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Collation' -Value 'SQL_Latin1_General_CP1_CI_AS' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'RecoveryModel' -Value 'Full' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'CompatibilityLevel' -Value 'Version150' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockParent | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' }, + @{ Name = 'SQL_Latin1_General_Pref_CP850_CI_AS' } + ) + } -Force + return $mockParent + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + # Mock implementation + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetOwner' -Value { + param($OwnerName) + # Mock implementation + } -Force + + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockDatabaseObject + } | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + # Mock implementation + } -PassThru -Force + } -Force + $mockServerObject | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' }, + @{ Name = 'SQL_Latin1_General_Pref_CP850_CI_AS' } + ) + } -Force + } + + It 'Should modify database properties successfully' { + Mock -CommandName 'Write-Verbose' + + { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -RecoveryModel 'Simple' -Force } | Should -Not -Throw + } + + It 'Should return database object when PassThru is specified' { + Mock -CommandName 'Write-Verbose' + + $result = Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -RecoveryModel 'Simple' -Force -PassThru + + $result | Should -Not -BeNullOrEmpty + $result.Name | Should -Be 'TestDatabase' + } + + It 'Should throw error when database does not exist' { + Mock -CommandName 'Write-Verbose' + + { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -RecoveryModel 'Simple' -Force } | + Should -Throw -ExpectedMessage '*not found*' + } + } + + Context 'When modifying a database using DatabaseObject' { + BeforeAll { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Collation' -Value 'SQL_Latin1_General_CP1_CI_AS' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'RecoveryModel' -Value 'Full' -Force + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'CompatibilityLevel' -Value 'Version150' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockParent | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' }, + @{ Name = 'SQL_Latin1_General_Pref_CP850_CI_AS' } + ) + } -Force + return $mockParent + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + # Mock implementation + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetOwner' -Value { + param($OwnerName) + # Mock implementation + } -Force + } + + It 'Should modify database using database object' { + Mock -CommandName 'Write-Verbose' + + { Set-SqlDscDatabase -DatabaseObject $mockDatabaseObject -RecoveryModel 'Simple' -Force } | Should -Not -Throw + } + } + + Context 'Parameter validation' { + It 'Should have the correct parameters in parameter set ServerObject' -ForEach @( + @{ + ExpectedParameterSetName = 'ServerObject' + ExpectedParameters = '-ServerObject -Name [-Collation ] [-CompatibilityLevel ] [-RecoveryModel ] [-OwnerName ] [-Force] [-Refresh] [-PassThru] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Set-SqlDscDatabase').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + + It 'Should have the correct parameters in parameter set DatabaseObject' -ForEach @( + @{ + ExpectedParameterSetName = 'DatabaseObject' + ExpectedParameters = '-DatabaseObject [-Collation ] [-CompatibilityLevel ] [-RecoveryModel ] [-OwnerName ] [-Force] [-PassThru] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Set-SqlDscDatabase').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + } +} \ No newline at end of file diff --git a/tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 new file mode 100644 index 0000000000..9069d92cfc --- /dev/null +++ b/tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 @@ -0,0 +1,195 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' + + # Loading mocked classes + Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '../Stubs') -ChildPath 'SMO.cs') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +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:dscModuleName -All | Remove-Module -Force + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Test-SqlDscDatabase' -Tag 'Public' { + Context 'When testing database presence' { + BeforeAll { + $mockExistingDatabase = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'Collation' -Value 'SQL_Latin1_General_CP1_CI_AS' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'CompatibilityLevel' -Value 'Version150' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'RecoveryModel' -Value 'Full' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'Owner' -Value 'sa' -Force + + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockExistingDatabase + } | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + # Mock implementation + } -PassThru -Force + } -Force + } + + It 'Should return true when database exists and Ensure is Present' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' + + $result | Should -BeTrue + } + + It 'Should return false when database does not exist and Ensure is Present' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Ensure 'Present' + + $result | Should -BeFalse + } + + It 'Should return false when database exists and Ensure is Absent' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Absent' + + $result | Should -BeFalse + } + + It 'Should return true when database does not exist and Ensure is Absent' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Ensure 'Absent' + + $result | Should -BeTrue + } + } + + Context 'When testing database properties' { + BeforeAll { + $mockExistingDatabase = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'Collation' -Value 'SQL_Latin1_General_CP1_CI_AS' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'CompatibilityLevel' -Value 'Version150' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'RecoveryModel' -Value 'Full' -Force + $mockExistingDatabase | Add-Member -MemberType 'NoteProperty' -Name 'Owner' -Value 'sa' -Force + + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockExistingDatabase + } | Add-Member -MemberType 'ScriptMethod' -Name 'Refresh' -Value { + # Mock implementation + } -PassThru -Force + } -Force + } + + It 'Should return true when all properties match' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -Collation 'SQL_Latin1_General_CP1_CI_AS' -CompatibilityLevel 'Version150' -RecoveryModel 'Full' -OwnerName 'sa' + + $result | Should -BeTrue + } + + It 'Should return false when collation does not match' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -Collation 'Different_Collation' + + $result | Should -BeFalse + } + + It 'Should return false when compatibility level does not match' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -CompatibilityLevel 'Version140' + + $result | Should -BeFalse + } + + It 'Should return false when recovery model does not match' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -RecoveryModel 'Simple' + + $result | Should -BeFalse + } + + It 'Should return false when owner does not match' { + Mock -CommandName 'Write-Verbose' + + $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -OwnerName 'DifferentOwner' + + $result | Should -BeFalse + } + } + + Context 'Parameter validation' { + It 'Should have the correct parameters in parameter set __AllParameterSets' -ForEach @( + @{ + ExpectedParameterSetName = '__AllParameterSets' + ExpectedParameters = '[-ServerObject] [-Name] [[-Ensure] ] [[-Collation] ] [[-CompatibilityLevel] ] [[-RecoveryModel] ] [[-OwnerName] ] [-Refresh] []' + } + ) { + $result = (Get-Command -Name 'Test-SqlDscDatabase').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + + It 'Should have ServerObject as a mandatory parameter' { + $parameterInfo = (Get-Command -Name 'Test-SqlDscDatabase').Parameters['ServerObject'] + $parameterInfo.Attributes.Mandatory | Should -BeTrue + } + + It 'Should have Name as a mandatory parameter' { + $parameterInfo = (Get-Command -Name 'Test-SqlDscDatabase').Parameters['Name'] + $parameterInfo.Attributes.Mandatory | Should -BeTrue + } + } +} \ No newline at end of file From ade4c3ed172fa6ca74289d8b15fbb3e6c659f311 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:57:55 +0000 Subject: [PATCH 03/15] Fix file endings and trailing whitespace in database commands - Remove trailing whitespace from line 111 in Remove-SqlDscDatabase.ps1 - Add exactly one blank line at the end of all new database command files - Resolves PSAvoidTrailingWhitespace linting rule violation Co-authored-by: johlju <7189721+johlju@users.noreply.github.com> --- source/Public/Get-SqlDscDatabase.ps1 | 2 +- source/Public/New-SqlDscDatabase.ps1 | 2 +- source/Public/Remove-SqlDscDatabase.ps1 | 4 ++-- source/Public/Set-SqlDscDatabase.ps1 | 2 +- source/Public/Test-SqlDscDatabase.ps1 | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/Public/Get-SqlDscDatabase.ps1 b/source/Public/Get-SqlDscDatabase.ps1 index 6d447a3285..c6d5016e52 100644 --- a/source/Public/Get-SqlDscDatabase.ps1 +++ b/source/Public/Get-SqlDscDatabase.ps1 @@ -100,4 +100,4 @@ function Get-SqlDscDatabase return [Microsoft.SqlServer.Management.Smo.Database[]] $databaseObject } -} \ No newline at end of file +} diff --git a/source/Public/New-SqlDscDatabase.ps1 b/source/Public/New-SqlDscDatabase.ps1 index baf95bd94f..ca656e3f8b 100644 --- a/source/Public/New-SqlDscDatabase.ps1 +++ b/source/Public/New-SqlDscDatabase.ps1 @@ -195,4 +195,4 @@ function New-SqlDscDatabase } } } -} \ No newline at end of file +} diff --git a/source/Public/Remove-SqlDscDatabase.ps1 b/source/Public/Remove-SqlDscDatabase.ps1 index d0895d2786..40475227a7 100644 --- a/source/Public/Remove-SqlDscDatabase.ps1 +++ b/source/Public/Remove-SqlDscDatabase.ps1 @@ -108,7 +108,7 @@ function Remove-SqlDscDatabase { $Name = $DatabaseObject.Name Write-Verbose -Message ($script:localizedData.Database_Remove -f $Name, $DatabaseObject.Parent.InstanceName) - + # Check if the database is a system database (cannot be dropped) $systemDatabases = @('master', 'model', 'msdb', 'tempdb') if ($Name -in $systemDatabases) @@ -139,4 +139,4 @@ function Remove-SqlDscDatabase } } } -} \ No newline at end of file +} diff --git a/source/Public/Set-SqlDscDatabase.ps1 b/source/Public/Set-SqlDscDatabase.ps1 index 3aa42100d0..afd5893f46 100644 --- a/source/Public/Set-SqlDscDatabase.ps1 +++ b/source/Public/Set-SqlDscDatabase.ps1 @@ -225,4 +225,4 @@ function Set-SqlDscDatabase } } } -} \ No newline at end of file +} diff --git a/source/Public/Test-SqlDscDatabase.ps1 b/source/Public/Test-SqlDscDatabase.ps1 index 5c973ae163..9eb05fb87b 100644 --- a/source/Public/Test-SqlDscDatabase.ps1 +++ b/source/Public/Test-SqlDscDatabase.ps1 @@ -165,4 +165,4 @@ function Test-SqlDscDatabase return $isDatabaseInDesiredState } -} \ No newline at end of file +} From 07097b3e71cf3392d1db0cb14c0c765ae76cb8b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:01:07 +0000 Subject: [PATCH 04/15] Add integration tests for Set-SqlDscDatabase and Remove-SqlDscDatabase commands Co-authored-by: johlju <7189721+johlju@users.noreply.github.com> --- azure-pipelines.yml | 5 + build.ps1 | 0 ...emove-SqlDscDatabase.Integration.Tests.ps1 | 151 +++++++++++++++++ .../Set-SqlDscDatabase.Integration.Tests.ps1 | 154 ++++++++++++++++++ 4 files changed, 310 insertions(+) mode change 100644 => 100755 build.ps1 create mode 100644 tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 create mode 100644 tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d24f8aef8f..4ce2e0b15d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -298,6 +298,11 @@ stages: 'tests/Integration/Commands/Get-SqlDscRole.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1' + 'tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' # Group 9 'tests/Integration/Commands/Uninstall-SqlDscServer.Integration.Tests.ps1' diff --git a/build.ps1 b/build.ps1 old mode 100644 new mode 100755 diff --git a/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 new file mode 100644 index 0000000000..a4163c9617 --- /dev/null +++ b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 @@ -0,0 +1,151 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + Import-Module -Name $script:dscModuleName +} + +Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + + $script:mockInstanceName = 'DSCSQLTEST' + $script:mockComputerName = Get-ComputerName + + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force + + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) + + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + } + + AfterAll { + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + + # Stop the named instance SQL Server service to save memory on the build worker. + Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + } + + Context 'When removing a database using ServerObject parameter set' { + BeforeEach { + # Create a test database for each test + $script:testDatabaseName = 'SqlDscTestRemoveDatabase_' + (Get-Random) + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + } + + It 'Should remove a database successfully' { + # Verify database exists before removal + $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $existingDb | Should -Not -BeNullOrEmpty + + # Remove the database + Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + + # Verify database no longer exists + $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'SilentlyContinue' + $removedDb | Should -BeNullOrEmpty + } + + It 'Should throw error when trying to remove non-existent database' { + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Force } | + Should -Throw -ExpectedMessage "*not found*" + } + } + + Context 'When removing a database using DatabaseObject parameter set' { + BeforeEach { + # Create a test database for each test + $script:testDatabaseNameForObject = 'SqlDscTestRemoveDatabaseObj_' + (Get-Random) + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force + } + + It 'Should remove a database using database object' { + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $databaseObject | Should -Not -BeNullOrEmpty + + # Remove the database using database object + Remove-SqlDscDatabase -DatabaseObject $databaseObject -Force + + # Verify database no longer exists + $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'SilentlyContinue' + $removedDb | Should -BeNullOrEmpty + } + + It 'Should support pipeline input with database object' { + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $databaseObject | Should -Not -BeNullOrEmpty + + # Remove the database using pipeline + $databaseObject | Remove-SqlDscDatabase -Force + + # Verify database no longer exists + $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'SilentlyContinue' + $removedDb | Should -BeNullOrEmpty + } + } + + Context 'When attempting to remove system databases' { + It 'Should throw error when trying to remove master database' { + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Force } | + Should -Throw -ExpectedMessage "*system database*" + } + + It 'Should throw error when trying to remove model database' { + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'model' -Force } | + Should -Throw -ExpectedMessage "*system database*" + } + + It 'Should throw error when trying to remove msdb database' { + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'msdb' -Force } | + Should -Throw -ExpectedMessage "*system database*" + } + + It 'Should throw error when trying to remove tempdb database' { + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'tempdb' -Force } | + Should -Throw -ExpectedMessage "*system database*" + } + } + + Context 'When using the Refresh parameter' { + BeforeEach { + # Create a test database for each test + $script:testDatabaseNameRefresh = 'SqlDscTestRemoveDatabaseRefresh_' + (Get-Random) + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Force + } + + It 'Should refresh the database collection before removing' { + # Remove the database with refresh + Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Refresh -Force + + # Verify database no longer exists + $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -ErrorAction 'SilentlyContinue' + $removedDb | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 new file mode 100644 index 0000000000..dfd473ae99 --- /dev/null +++ b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 @@ -0,0 +1,154 @@ +[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 build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'SqlServerDsc' + + Import-Module -Name $script:dscModuleName +} + +Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { + BeforeAll { + # Starting the named instance SQL Server service prior to running tests. + Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + + $script:mockInstanceName = 'DSCSQLTEST' + $script:mockComputerName = Get-ComputerName + + $mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception. + $mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force + + $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) + + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + + # Test database names + $script:testDatabaseName = 'SqlDscTestSetDatabase_' + (Get-Random) + $script:testDatabaseNameForObject = 'SqlDscTestSetDatabaseObj_' + (Get-Random) + + # Create test databases + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force + } + + AfterAll { + # Clean up test databases + $testDatabasesToRemove = @($script:testDatabaseName, $script:testDatabaseNameForObject) + + foreach ($dbName in $testDatabasesToRemove) { + $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $dbName -ErrorAction 'SilentlyContinue' + if ($existingDb) { + Remove-SqlDscDatabase -DatabaseObject $existingDb -Force + } + } + + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + + # Stop the named instance SQL Server service to save memory on the build worker. + Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' + } + + Context 'When setting database properties using ServerObject parameter set' { + It 'Should set recovery model successfully' { + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -Force + + # Verify the change + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $updatedDb.RecoveryModel | Should -Be 'Simple' + } + + It 'Should set owner name successfully' { + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -OwnerName 'sa' -Force + + # Verify the change + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $updatedDb.Owner | Should -Be 'sa' + } + + It 'Should set multiple properties successfully' { + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Full' -OwnerName 'sa' -Force + + # Verify the changes + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $updatedDb.RecoveryModel | Should -Be 'Full' + $updatedDb.Owner | Should -Be 'sa' + } + + It 'Should throw error when trying to set properties of non-existent database' { + { Set-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -RecoveryModel 'Simple' -Force } | + Should -Throw -ExpectedMessage "*not found*" + } + } + + Context 'When setting database properties using DatabaseObject parameter set' { + It 'Should set recovery model using database object' { + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + Set-SqlDscDatabase -DatabaseObject $databaseObject -RecoveryModel 'Simple' -Force + + # Verify the change + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $updatedDb.RecoveryModel | Should -Be 'Simple' + } + + It 'Should set owner name using database object' { + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + Set-SqlDscDatabase -DatabaseObject $databaseObject -OwnerName 'sa' -Force + + # Verify the change + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $updatedDb.Owner | Should -Be 'sa' + } + + It 'Should support pipeline input with database object' { + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $databaseObject | Set-SqlDscDatabase -RecoveryModel 'Full' -Force + + # Verify the change + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $updatedDb.RecoveryModel | Should -Be 'Full' + } + } + + Context 'When using the Refresh parameter' { + It 'Should refresh the database collection before setting properties' { + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'BulkLogged' -Refresh -Force + + # Verify the change + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $updatedDb.RecoveryModel | Should -Be 'BulkLogged' + } + } + + Context 'When using the PassThru parameter' { + It 'Should return the database object when PassThru is specified' { + $result = Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -PassThru -Force + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Database' + $result.Name | Should -Be $script:testDatabaseName + $result.RecoveryModel | Should -Be 'Simple' + } + } +} \ No newline at end of file From 88b838871dcc3bd3aacef916ee629fdba8de49fc Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Wed, 27 Aug 2025 20:06:51 +0200 Subject: [PATCH 05/15] Fix integration test --- .../Set-SqlDscDatabase.Integration.Tests.ps1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 index dfd473ae99..e59ff11548 100644 --- a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 @@ -44,7 +44,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential - # Test database names + # Test database names $script:testDatabaseName = 'SqlDscTestSetDatabase_' + (Get-Random) $script:testDatabaseNameForObject = 'SqlDscTestSetDatabaseObj_' + (Get-Random) @@ -56,7 +56,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 AfterAll { # Clean up test databases $testDatabasesToRemove = @($script:testDatabaseName, $script:testDatabaseNameForObject) - + foreach ($dbName in $testDatabasesToRemove) { $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $dbName -ErrorAction 'SilentlyContinue' if ($existingDb) { @@ -80,7 +80,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 } It 'Should set owner name successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -OwnerName 'sa' -Force + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName @@ -88,7 +88,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 } It 'Should set multiple properties successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Full' -OwnerName 'sa' -Force + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Full' -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force # Verify the changes $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName @@ -114,7 +114,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 It 'Should set owner name using database object' { $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject - Set-SqlDscDatabase -DatabaseObject $databaseObject -OwnerName 'sa' -Force + Set-SqlDscDatabase -DatabaseObject $databaseObject -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject @@ -151,4 +151,4 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 $result.RecoveryModel | Should -Be 'Simple' } } -} \ No newline at end of file +} From 9ef342a19426c292dfb42ffaa65a7dec9afa4e39 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Thu, 28 Aug 2025 12:05:25 +0200 Subject: [PATCH 06/15] Fix integraiton tests --- .../Set-SqlDscDatabase.Integration.Tests.ps1 | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 index e59ff11548..ed6f9dca53 100644 --- a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 @@ -49,8 +49,8 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 $script:testDatabaseNameForObject = 'SqlDscTestSetDatabaseObj_' + (Get-Random) # Create test databases - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction 'Stop' + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force -ErrorAction 'Stop' } AfterAll { @@ -72,7 +72,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 Context 'When setting database properties using ServerObject parameter set' { It 'Should set recovery model successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -Force + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -Force -ErrorAction 'Stop' # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName @@ -80,70 +80,70 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 } It 'Should set owner name successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' # Verify the change - $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName - $updatedDb.Owner | Should -Be 'sa' + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'Stop' + $updatedDb.Owner | Should -Be ('{0}\SqlAdmin' -f $script:mockComputerName) } It 'Should set multiple properties successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Full' -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Full' -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' # Verify the changes - $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'Stop' $updatedDb.RecoveryModel | Should -Be 'Full' - $updatedDb.Owner | Should -Be 'sa' + $updatedDb.Owner | Should -Be ('{0}\SqlAdmin' -f $script:mockComputerName) } It 'Should throw error when trying to set properties of non-existent database' { - { Set-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -RecoveryModel 'Simple' -Force } | - Should -Throw -ExpectedMessage "*not found*" + { Set-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -RecoveryModel 'Simple' -Force -ErrorAction 'Stop' } | + Should -Throw } } Context 'When setting database properties using DatabaseObject parameter set' { It 'Should set recovery model using database object' { - $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject - Set-SqlDscDatabase -DatabaseObject $databaseObject -RecoveryModel 'Simple' -Force + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' + Set-SqlDscDatabase -DatabaseObject $databaseObject -RecoveryModel 'Simple' -Force -ErrorAction 'Stop' # Verify the change - $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' $updatedDb.RecoveryModel | Should -Be 'Simple' } It 'Should set owner name using database object' { - $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject - Set-SqlDscDatabase -DatabaseObject $databaseObject -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' + Set-SqlDscDatabase -DatabaseObject $databaseObject -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' # Verify the change - $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject - $updatedDb.Owner | Should -Be 'sa' + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' + $updatedDb.Owner | Should -Be ('{0}\SqlAdmin' -f $script:mockComputerName) } It 'Should support pipeline input with database object' { - $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject - $databaseObject | Set-SqlDscDatabase -RecoveryModel 'Full' -Force + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' + $databaseObject | Set-SqlDscDatabase -RecoveryModel 'Full' -Force -ErrorAction 'Stop' # Verify the change - $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' $updatedDb.RecoveryModel | Should -Be 'Full' } } Context 'When using the Refresh parameter' { It 'Should refresh the database collection before setting properties' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'BulkLogged' -Refresh -Force + Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'BulkLogged' -Refresh -Force -ErrorAction 'Stop' # Verify the change - $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'Stop' $updatedDb.RecoveryModel | Should -Be 'BulkLogged' } } Context 'When using the PassThru parameter' { It 'Should return the database object when PassThru is specified' { - $result = Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -PassThru -Force + $result = Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -PassThru -Force -ErrorAction 'Stop' $result | Should -Not -BeNullOrEmpty $result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Database' From a76a24c917c76909ea214cfb70082608139bb1d8 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Thu, 28 Aug 2025 12:22:17 +0200 Subject: [PATCH 07/15] FIx review commenrts --- source/Public/New-SqlDscDatabase.ps1 | 14 ++++-- .../Get-SqlDscDatabase.Integration.Tests.ps1 | 6 +-- .../New-SqlDscDatabase.Integration.Tests.ps1 | 42 +++++++++-------- ...emove-SqlDscDatabase.Integration.Tests.ps1 | 46 +++++++++---------- .../Set-SqlDscDatabase.Integration.Tests.ps1 | 9 ++-- .../Test-SqlDscDatabase.Integration.Tests.ps1 | 4 +- 6 files changed, 69 insertions(+), 52 deletions(-) diff --git a/source/Public/New-SqlDscDatabase.ps1 b/source/Public/New-SqlDscDatabase.ps1 index ca656e3f8b..3eee2586dc 100644 --- a/source/Public/New-SqlDscDatabase.ps1 +++ b/source/Public/New-SqlDscDatabase.ps1 @@ -96,6 +96,14 @@ function New-SqlDscDatabase $Refresh ) + begin + { + if ($Force.IsPresent -and -not $Confirm) + { + $ConfirmPreference = 'None' + } + } + process { if ($Refresh.IsPresent) @@ -131,7 +139,7 @@ function New-SqlDscDatabase if ($CompatibilityLevel -notin $supportedCompatibilityLevels.$($ServerObject.VersionMajor)) { $errorMessage = $script:localizedData.Database_InvalidCompatibilityLevel -f $CompatibilityLevel, $ServerObject.InstanceName - New-ObjectNotFoundException -Message $errorMessage + New-InvalidArgumentException -ArgumentName 'CompatibilityLevel' -Message $errorMessage } } @@ -141,7 +149,7 @@ function New-SqlDscDatabase if ($Collation -notin $ServerObject.EnumCollations().Name) { $errorMessage = $script:localizedData.Database_InvalidCollation -f $Collation, $ServerObject.InstanceName - New-ObjectNotFoundException -Message $errorMessage + New-InvalidArgumentException -ArgumentName 'Collation' -Message $errorMessage } } @@ -149,7 +157,7 @@ function New-SqlDscDatabase $verboseWarningMessage = $script:localizedData.Database_Create_ShouldProcessVerboseWarning -f $Name $captionMessage = $script:localizedData.Database_Create_ShouldProcessCaption - if ($Force.IsPresent -or $PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) + if ($PSCmdlet.ShouldProcess($verboseDescriptionMessage, $verboseWarningMessage, $captionMessage)) { try { diff --git a/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 index d5681a1915..d262663dd3 100644 --- a/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1 @@ -29,7 +29,7 @@ BeforeAll { Import-Module -Name $script:dscModuleName } -Describe 'Get-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Get-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' @@ -85,7 +85,7 @@ Describe 'Get-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 It 'Should throw error when getting a non-existent database' { { Get-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -ErrorAction 'Stop' } | - Should -Throw -ExpectedMessage "*not found*" + Should -Throw } It 'Should return nothing when getting a non-existent database with SilentlyContinue' { @@ -103,4 +103,4 @@ Describe 'Get-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 $result.Name | Should -Contain 'master' } } -} \ No newline at end of file +} diff --git a/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 index ea756c166f..09e47bbbd9 100644 --- a/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 @@ -29,7 +29,7 @@ BeforeAll { Import-Module -Name $script:dscModuleName } -Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' @@ -42,9 +42,9 @@ Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) - $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -ErrorAction Stop - # Test database names + # Test database names $script:testDatabaseName = 'SqlDscTestDatabase_' + (Get-Random) $script:testDatabaseNameWithProperties = 'SqlDscTestDatabaseWithProps_' + (Get-Random) } @@ -52,10 +52,13 @@ Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 AfterAll { # Clean up test databases $testDatabasesToRemove = @($script:testDatabaseName, $script:testDatabaseNameWithProperties) - - foreach ($dbName in $testDatabasesToRemove) { + + foreach ($dbName in $testDatabasesToRemove) + { $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $dbName -ErrorAction 'SilentlyContinue' - if ($existingDb) { + + if ($existingDb) + { Remove-SqlDscDatabase -DatabaseObject $existingDb -Force } } @@ -68,53 +71,56 @@ Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 Context 'When creating a new database' { It 'Should create a database successfully with minimal parameters' { - $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop $result | Should -Not -BeNullOrEmpty $result.Name | Should -Be $script:testDatabaseName $result | Should -BeOfType 'Microsoft.SqlServer.Management.Smo.Database' # Verify the database exists - $createdDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $createdDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction Stop $createdDb | Should -Not -BeNullOrEmpty } It 'Should create a database with specified properties' { - $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameWithProperties -RecoveryModel 'Simple' -Force + $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameWithProperties -RecoveryModel 'Simple' -Force -ErrorAction Stop $result | Should -Not -BeNullOrEmpty $result.Name | Should -Be $script:testDatabaseNameWithProperties $result.RecoveryModel | Should -Be 'Simple' # Verify the database exists with correct properties - $createdDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameWithProperties + $createdDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameWithProperties -ErrorAction Stop $createdDb | Should -Not -BeNullOrEmpty $createdDb.RecoveryModel | Should -Be 'Simple' } It 'Should throw error when trying to create a database that already exists' { - { New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force } | - Should -Throw -ExpectedMessage "*already exists*" + { New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop } | + Should -Throw } } Context 'When using the Refresh parameter' { It 'Should refresh the database collection before creating' { $uniqueName = 'SqlDscTestRefresh_' + (Get-Random) - - try { - $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $uniqueName -Refresh -Force + + try + { + $result = New-SqlDscDatabase -ServerObject $script:serverObject -Name $uniqueName -Refresh -Force -ErrorAction Stop $result | Should -Not -BeNullOrEmpty $result.Name | Should -Be $uniqueName } - finally { + finally + { # Clean up $dbToRemove = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $uniqueName -ErrorAction 'SilentlyContinue' - if ($dbToRemove) { + if ($dbToRemove) + { Remove-SqlDscDatabase -DatabaseObject $dbToRemove -Force } } } } -} \ No newline at end of file +} diff --git a/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 index a4163c9617..03292b57d6 100644 --- a/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 @@ -29,7 +29,7 @@ BeforeAll { Import-Module -Name $script:dscModuleName } -Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' @@ -42,7 +42,7 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2 $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) - $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -ErrorAction Stop } AfterAll { @@ -56,16 +56,16 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2 BeforeEach { # Create a test database for each test $script:testDatabaseName = 'SqlDscTestRemoveDatabase_' + (Get-Random) - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop } It 'Should remove a database successfully' { # Verify database exists before removal - $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName + $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction Stop $existingDb | Should -Not -BeNullOrEmpty # Remove the database - Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force + Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop # Verify database no longer exists $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'SilentlyContinue' @@ -73,8 +73,8 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2 } It 'Should throw error when trying to remove non-existent database' { - { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Force } | - Should -Throw -ExpectedMessage "*not found*" + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Force -ErrorAction Stop } | + Should -Throw } } @@ -82,15 +82,15 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2 BeforeEach { # Create a test database for each test $script:testDatabaseNameForObject = 'SqlDscTestRemoveDatabaseObj_' + (Get-Random) - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force -ErrorAction Stop } It 'Should remove a database using database object' { - $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction Stop $databaseObject | Should -Not -BeNullOrEmpty # Remove the database using database object - Remove-SqlDscDatabase -DatabaseObject $databaseObject -Force + Remove-SqlDscDatabase -DatabaseObject $databaseObject -Force -ErrorAction Stop # Verify database no longer exists $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'SilentlyContinue' @@ -98,11 +98,11 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2 } It 'Should support pipeline input with database object' { - $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject + $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction Stop $databaseObject | Should -Not -BeNullOrEmpty # Remove the database using pipeline - $databaseObject | Remove-SqlDscDatabase -Force + $databaseObject | Remove-SqlDscDatabase -Force -ErrorAction Stop # Verify database no longer exists $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'SilentlyContinue' @@ -112,23 +112,23 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2 Context 'When attempting to remove system databases' { It 'Should throw error when trying to remove master database' { - { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Force } | - Should -Throw -ExpectedMessage "*system database*" + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Force -ErrorAction Stop } | + Should -Throw } It 'Should throw error when trying to remove model database' { - { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'model' -Force } | - Should -Throw -ExpectedMessage "*system database*" + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'model' -Force -ErrorAction Stop } | + Should -Throw } It 'Should throw error when trying to remove msdb database' { - { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'msdb' -Force } | - Should -Throw -ExpectedMessage "*system database*" + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'msdb' -Force -ErrorAction Stop } | + Should -Throw } It 'Should throw error when trying to remove tempdb database' { - { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'tempdb' -Force } | - Should -Throw -ExpectedMessage "*system database*" + { Remove-SqlDscDatabase -ServerObject $script:serverObject -Name 'tempdb' -Force -ErrorAction Stop } | + Should -Throw } } @@ -136,16 +136,16 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2 BeforeEach { # Create a test database for each test $script:testDatabaseNameRefresh = 'SqlDscTestRemoveDatabaseRefresh_' + (Get-Random) - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Force + New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Force -ErrorAction Stop } It 'Should refresh the database collection before removing' { # Remove the database with refresh - Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Refresh -Force + Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Refresh -Force -ErrorAction Stop # Verify database no longer exists $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -ErrorAction 'SilentlyContinue' $removedDb | Should -BeNullOrEmpty } } -} \ No newline at end of file +} diff --git a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 index ed6f9dca53..aeea45e548 100644 --- a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 @@ -29,7 +29,7 @@ BeforeAll { Import-Module -Name $script:dscModuleName } -Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { +Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { BeforeAll { # Starting the named instance SQL Server service prior to running tests. Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' @@ -57,9 +57,12 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017 # Clean up test databases $testDatabasesToRemove = @($script:testDatabaseName, $script:testDatabaseNameForObject) - foreach ($dbName in $testDatabasesToRemove) { + foreach ($dbName in $testDatabasesToRemove) + { $existingDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $dbName -ErrorAction 'SilentlyContinue' - if ($existingDb) { + + if ($existingDb) + { Remove-SqlDscDatabase -DatabaseObject $existingDb -Force } } diff --git a/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 index a3385a4e0f..24680c7fbf 100644 --- a/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 @@ -26,7 +26,7 @@ BeforeDiscovery { BeforeAll { $script:dscModuleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' } Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { @@ -101,4 +101,4 @@ Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL201 $result | Should -BeTrue } } -} \ No newline at end of file +} From 7fadb6dea9c32843b18838e7c9657ef7c5e3fef5 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Thu, 28 Aug 2025 14:05:31 +0200 Subject: [PATCH 08/15] DEBUG 1 --- azure-pipelines.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ffc76a1ded..331c5018c8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -302,10 +302,10 @@ stages: 'tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1' 'tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1' - 'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1' - 'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1' - 'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1' - 'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' + #'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1' + #'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1' + #'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1' + #'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' 'tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1' 'tests/Integration/Commands/New-SqlDscAgentAlert.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscAgentAlert.Integration.Tests.ps1' From 4d458efdb530a4bb932a225cb8cd555bffe1a075 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Thu, 28 Aug 2025 17:38:29 +0200 Subject: [PATCH 09/15] DEBUG 2 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 331c5018c8..707840a4b8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -302,7 +302,7 @@ stages: 'tests/Integration/Commands/Remove-SqlDscRole.Integration.Tests.ps1' 'tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1' 'tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1' - #'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1' #'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1' #'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1' #'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' From 1d4a1b5efcf99961a23b2313c99c472eabb773e6 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 29 Aug 2025 16:32:19 +0200 Subject: [PATCH 10/15] DEBUG 3 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 707840a4b8..9ae890dc7d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -303,7 +303,7 @@ stages: 'tests/Integration/Commands/Remove-SqlDscLogin.Integration.Tests.ps1' 'tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1' 'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1' - #'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1' #'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1' #'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' 'tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1' From 4982d91d933e272c09cf2a817f4d2d772a0065ed Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 29 Aug 2025 18:04:35 +0200 Subject: [PATCH 11/15] DEBUF 4 --- .../Set-SqlDscDatabase.Integration.Tests.ps1 | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 index aeea45e548..18f12708b1 100644 --- a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 @@ -49,8 +49,8 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 $script:testDatabaseNameForObject = 'SqlDscTestSetDatabaseObj_' + (Get-Random) # Create test databases - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction 'Stop' - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force -ErrorAction 'Stop' + $null = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction 'Stop' + $null = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force -ErrorAction 'Stop' } AfterAll { @@ -63,7 +63,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 if ($existingDb) { - Remove-SqlDscDatabase -DatabaseObject $existingDb -Force + Remove-SqlDscDatabase -DatabaseObject $existingDb -Force -ErrorAction 'Stop' } } @@ -75,7 +75,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 Context 'When setting database properties using ServerObject parameter set' { It 'Should set recovery model successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -Force -ErrorAction 'Stop' + $null = Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Simple' -Force -ErrorAction 'Stop' # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName @@ -83,7 +83,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 } It 'Should set owner name successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' + $null = Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'Stop' @@ -91,7 +91,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 } It 'Should set multiple properties successfully' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Full' -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' + $null = Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'Full' -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' # Verify the changes $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'Stop' @@ -108,7 +108,8 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 Context 'When setting database properties using DatabaseObject parameter set' { It 'Should set recovery model using database object' { $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' - Set-SqlDscDatabase -DatabaseObject $databaseObject -RecoveryModel 'Simple' -Force -ErrorAction 'Stop' + + $null = Set-SqlDscDatabase -DatabaseObject $databaseObject -RecoveryModel 'Simple' -Force -ErrorAction 'Stop' # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' @@ -117,7 +118,8 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 It 'Should set owner name using database object' { $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' - Set-SqlDscDatabase -DatabaseObject $databaseObject -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' + + $null = Set-SqlDscDatabase -DatabaseObject $databaseObject -OwnerName ('{0}\SqlAdmin' -f $script:mockComputerName) -Force -ErrorAction 'Stop' # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' @@ -126,7 +128,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 It 'Should support pipeline input with database object' { $databaseObject = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' - $databaseObject | Set-SqlDscDatabase -RecoveryModel 'Full' -Force -ErrorAction 'Stop' + $null = $databaseObject | Set-SqlDscDatabase -RecoveryModel 'Full' -Force -ErrorAction 'Stop' # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'Stop' @@ -136,7 +138,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 Context 'When using the Refresh parameter' { It 'Should refresh the database collection before setting properties' { - Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'BulkLogged' -Refresh -Force -ErrorAction 'Stop' + $null = Set-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -RecoveryModel 'BulkLogged' -Refresh -Force -ErrorAction 'Stop' # Verify the change $updatedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'Stop' From bceea2f80ae84d560639bab38984f25866991295 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 29 Aug 2025 19:08:55 +0200 Subject: [PATCH 12/15] Fix review comments --- azure-pipelines.yml | 4 ++-- .../New-SqlDscDatabase.Integration.Tests.ps1 | 6 +++--- ...Remove-SqlDscDatabase.Integration.Tests.ps1 | 12 ++++++------ .../Set-SqlDscDatabase.Integration.Tests.ps1 | 2 +- .../Test-SqlDscDatabase.Integration.Tests.ps1 | 18 +++++++++--------- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9ae890dc7d..ffc76a1ded 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -304,8 +304,8 @@ stages: 'tests/Integration/Commands/Get-SqlDscDatabase.Integration.Tests.ps1' 'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1' - #'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1' - #'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1' + 'tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1' 'tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1' 'tests/Integration/Commands/New-SqlDscAgentAlert.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscAgentAlert.Integration.Tests.ps1' diff --git a/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 index 09e47bbbd9..4a57ecec12 100644 --- a/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1 @@ -26,7 +26,7 @@ BeforeDiscovery { BeforeAll { $script:dscModuleName = 'SqlServerDsc' - Import-Module -Name $script:dscModuleName + Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop' } Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') { @@ -59,7 +59,7 @@ Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 if ($existingDb) { - Remove-SqlDscDatabase -DatabaseObject $existingDb -Force + $null = Remove-SqlDscDatabase -DatabaseObject $existingDb -Force -ErrorAction 'Stop' } } @@ -118,7 +118,7 @@ Describe 'New-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 $dbToRemove = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $uniqueName -ErrorAction 'SilentlyContinue' if ($dbToRemove) { - Remove-SqlDscDatabase -DatabaseObject $dbToRemove -Force + $null = Remove-SqlDscDatabase -DatabaseObject $dbToRemove -Force } } } diff --git a/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 index 03292b57d6..b81dff88ed 100644 --- a/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Remove-SqlDscDatabase.Integration.Tests.ps1 @@ -56,7 +56,7 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2 BeforeEach { # Create a test database for each test $script:testDatabaseName = 'SqlDscTestRemoveDatabase_' + (Get-Random) - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop + $null = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop } It 'Should remove a database successfully' { @@ -65,7 +65,7 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2 $existingDb | Should -Not -BeNullOrEmpty # Remove the database - Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop + $null = Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction Stop # Verify database no longer exists $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -ErrorAction 'SilentlyContinue' @@ -82,7 +82,7 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2 BeforeEach { # Create a test database for each test $script:testDatabaseNameForObject = 'SqlDscTestRemoveDatabaseObj_' + (Get-Random) - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force -ErrorAction Stop + $null = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -Force -ErrorAction Stop } It 'Should remove a database using database object' { @@ -90,7 +90,7 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2 $databaseObject | Should -Not -BeNullOrEmpty # Remove the database using database object - Remove-SqlDscDatabase -DatabaseObject $databaseObject -Force -ErrorAction Stop + $null = Remove-SqlDscDatabase -DatabaseObject $databaseObject -Force -ErrorAction Stop # Verify database no longer exists $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameForObject -ErrorAction 'SilentlyContinue' @@ -136,12 +136,12 @@ Describe 'Remove-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2 BeforeEach { # Create a test database for each test $script:testDatabaseNameRefresh = 'SqlDscTestRemoveDatabaseRefresh_' + (Get-Random) - New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Force -ErrorAction Stop + $null = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Force -ErrorAction Stop } It 'Should refresh the database collection before removing' { # Remove the database with refresh - Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Refresh -Force -ErrorAction Stop + $null = Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -Refresh -Force -ErrorAction Stop # Verify database no longer exists $removedDb = Get-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseNameRefresh -ErrorAction 'SilentlyContinue' diff --git a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 index 18f12708b1..e475d9e9f6 100644 --- a/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1 @@ -63,7 +63,7 @@ Describe 'Set-SqlDscDatabase' -Tag @('Integration_SQL2017', 'Integration_SQL2019 if ($existingDb) { - Remove-SqlDscDatabase -DatabaseObject $existingDb -Force -ErrorAction 'Stop' + $null = Remove-SqlDscDatabase -DatabaseObject $existingDb -Force -ErrorAction 'Stop' } } diff --git a/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 index 24680c7fbf..a592d4c992 100644 --- a/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1 @@ -42,11 +42,11 @@ Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL201 $script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword) - $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential + $script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -ErrorAction 'Stop' } AfterAll { - Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject + Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject -ErrorAction 'Stop' # Stop the named instance SQL Server service to save memory on the build worker. Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop' @@ -54,25 +54,25 @@ Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL201 Context 'When testing database presence' { It 'Should return true when system database exists and Ensure is Present' { - $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -ErrorAction 'Stop' $result | Should -BeTrue } It 'Should return false when non-existent database is tested with Ensure Present' { - $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Ensure 'Present' + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Ensure 'Present' -ErrorAction 'Stop' $result | Should -BeFalse } It 'Should return false when system database exists and Ensure is Absent' { - $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Absent' + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Absent' -ErrorAction 'Stop' $result | Should -BeFalse } It 'Should return true when non-existent database is tested with Ensure Absent' { - $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Ensure 'Absent' + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'NonExistentDatabase' -Ensure 'Absent' -ErrorAction 'Stop' $result | Should -BeTrue } @@ -81,14 +81,14 @@ Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL201 Context 'When testing database properties' { It 'Should return true when testing master database with correct recovery model' { # Master database typically has Simple recovery model - $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -RecoveryModel 'Simple' + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -RecoveryModel 'Simple' -ErrorAction 'Stop' $result | Should -BeTrue } It 'Should return false when testing master database with incorrect recovery model' { # Master database typically has Simple recovery model, so Full should return false - $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -RecoveryModel 'Full' + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -RecoveryModel 'Full' -ErrorAction 'Stop' $result | Should -BeFalse } @@ -96,7 +96,7 @@ Describe 'Test-SqlDscDatabase' -Tag @('Integration_SQL2016', 'Integration_SQL201 Context 'When using the Refresh parameter' { It 'Should refresh the database collection and test database presence' { - $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -Refresh + $result = Test-SqlDscDatabase -ServerObject $script:serverObject -Name 'master' -Ensure 'Present' -Refresh -ErrorAction 'Stop' $result | Should -BeTrue } From fcffe4263667a5a78f4b9d905c55b457890add27 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 Aug 2025 17:41:20 +0000 Subject: [PATCH 13/15] Add unit test coverage for CompatibilityLevel, Collation, and OwnerName parameters Co-authored-by: johlju <7189721+johlju@users.noreply.github.com> --- .../Unit/Public/New-SqlDscDatabase.Tests.ps1 | 31 ++++ .../Public/Remove-SqlDscDatabase.Tests.ps1 | 15 ++ .../Unit/Public/Set-SqlDscDatabase.Tests.ps1 | 144 ++++++++++++++++++ 3 files changed, 190 insertions(+) diff --git a/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 index 40882af06b..3451e6eb0d 100644 --- a/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 @@ -120,6 +120,37 @@ Describe 'New-SqlDscDatabase' -Tag 'Public' { } } + Context 'When testing parameter validation errors' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{} + } -Force + $mockServerObject | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' }, + @{ Name = 'SQL_Latin1_General_Pref_CP850_CI_AS' } + ) + } -Force + } + + It 'Should throw error when CompatibilityLevel is invalid for SQL Server version' { + Mock -CommandName 'Write-Verbose' + + { New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDB' -CompatibilityLevel 'Version80' -Force } | + Should -Throw -ExpectedMessage '*not a valid compatibility level*' + } + + It 'Should throw error when Collation is invalid' { + Mock -CommandName 'Write-Verbose' + + { New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDB' -Collation 'InvalidCollation' -Force } | + Should -Throw -ExpectedMessage '*not a valid collation*' + } + } + Context 'Parameter validation' { It 'Should have the correct parameters in parameter set __AllParameterSets' -ForEach @( @{ diff --git a/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 index 6459b77902..4593e2bac4 100644 --- a/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 @@ -115,6 +115,21 @@ Describe 'Remove-SqlDscDatabase' -Tag 'Public' { { Remove-SqlDscDatabase -DatabaseObject $mockDatabaseObject -Force } | Should -Not -Throw } + + It 'Should throw error when trying to remove system database using DatabaseObject' { + $mockSystemDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockSystemDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'master' -Force + $mockSystemDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + return $mockParent + } -Force + + Mock -CommandName 'Write-Verbose' + + { Remove-SqlDscDatabase -DatabaseObject $mockSystemDatabaseObject -Force } | + Should -Throw -ExpectedMessage '*Cannot remove system database*' + } } Context 'Parameter validation' { diff --git a/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 index 6aeabf12c6..82d9416fa3 100644 --- a/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 @@ -153,6 +153,150 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { } } + Context 'When testing CompatibilityLevel parameter validation' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + return @{ + 'TestDatabase' = $mockDatabaseObject + } + } -Force + $mockServerObject | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' } + ) + } -Force + } + + It 'Should throw error when CompatibilityLevel is invalid for SQL Server version' { + Mock -CommandName 'Write-Verbose' + + { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -CompatibilityLevel 'Version80' -Force } | + Should -Throw -ExpectedMessage '*not a valid compatibility level*' + } + + It 'Should allow valid CompatibilityLevel for SQL Server version' { + Mock -CommandName 'Write-Verbose' + + # We only test that the validation passes, not the actual property setting + $mockServerObjectWithValidDb = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObjectWithValidDb | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObjectWithValidDb | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockDatabaseObjectWithValidProps = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObjectWithValidProps | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObjectWithValidProps | Add-Member -MemberType 'NoteProperty' -Name 'CompatibilityLevel' -Value 'Version150' -Force + $mockDatabaseObjectWithValidProps | Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + # Mock implementation + } -Force + $mockServerObjectWithValidDb | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockDatabaseObjectWithValidProps + } + } -Force + $mockServerObjectWithValidDb | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' } + ) + } -Force + + { Set-SqlDscDatabase -ServerObject $mockServerObjectWithValidDb -Name 'TestDatabase' -CompatibilityLevel 'Version150' -Force } | Should -Not -Throw + } + } + + Context 'When testing Collation parameter validation' { + BeforeAll { + $mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObject | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockServerObject | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + # Mock implementation + } -Force + return @{ + 'TestDatabase' = $mockDatabaseObject + } + } -Force + $mockServerObject | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' }, + @{ Name = 'SQL_Latin1_General_Pref_CP850_CI_AS' } + ) + } -Force + } + + It 'Should throw error when Collation is invalid' { + Mock -CommandName 'Write-Verbose' + + { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Collation 'InvalidCollation' -Force } | + Should -Throw -ExpectedMessage '*not a valid collation*' + } + + It 'Should allow valid Collation' { + Mock -CommandName 'Write-Verbose' + + $mockServerObjectWithValidDb = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockServerObjectWithValidDb | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockServerObjectWithValidDb | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockDatabaseObjectWithValidProps = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObjectWithValidProps | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObjectWithValidProps | Add-Member -MemberType 'NoteProperty' -Name 'Collation' -Value 'SQL_Latin1_General_CP1_CI_AS' -Force + $mockDatabaseObjectWithValidProps | Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + # Mock implementation + } -Force + $mockServerObjectWithValidDb | Add-Member -MemberType 'ScriptProperty' -Name 'Databases' -Value { + return @{ + 'TestDatabase' = $mockDatabaseObjectWithValidProps + } + } -Force + $mockServerObjectWithValidDb | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' }, + @{ Name = 'SQL_Latin1_General_Pref_CP850_CI_AS' } + ) + } -Force + + { Set-SqlDscDatabase -ServerObject $mockServerObjectWithValidDb -Name 'TestDatabase' -Collation 'SQL_Latin1_General_CP1_CI_AS' -Force } | Should -Not -Throw + } + } + + Context 'When testing OwnerName parameter usage' { + BeforeAll { + $mockDatabaseObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Database' + $mockDatabaseObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestDatabase' -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptProperty' -Name 'Parent' -Value { + $mockParent = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force + $mockParent | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force + $mockParent | Add-Member -MemberType 'ScriptMethod' -Name 'EnumCollations' -Value { + return @( + @{ Name = 'SQL_Latin1_General_CP1_CI_AS' } + ) + } -Force + return $mockParent + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'Alter' -Value { + # Mock implementation + } -Force + $mockDatabaseObject | Add-Member -MemberType 'ScriptMethod' -Name 'SetOwner' -Value { + param($OwnerName) + # Mock implementation + } -Force + } + + It 'Should call SetOwner when OwnerName parameter is specified' { + Mock -CommandName 'Write-Verbose' + + # This tests that the OwnerName parameter usage path (line 202) is covered + { Set-SqlDscDatabase -DatabaseObject $mockDatabaseObject -OwnerName 'sa' -Force } | Should -Not -Throw + } + } + Context 'Parameter validation' { It 'Should have the correct parameters in parameter set ServerObject' -ForEach @( @{ From dd5a18c5c88025be7db1c692de6170f937d14992 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:02:12 +0000 Subject: [PATCH 14/15] Remove Write-Verbose mocks and fix -Not -Throw patterns in database command tests Co-authored-by: johlju <7189721+johlju@users.noreply.github.com> --- .../Unit/Public/Get-SqlDscDatabase.Tests.ps1 | 10 ------- .../Unit/Public/New-SqlDscDatabase.Tests.ps1 | 8 ------ .../Public/Remove-SqlDscDatabase.Tests.ps1 | 14 ++-------- .../Unit/Public/Set-SqlDscDatabase.Tests.ps1 | 28 ++++--------------- .../Unit/Public/Test-SqlDscDatabase.Tests.ps1 | 9 ------ 5 files changed, 7 insertions(+), 62 deletions(-) diff --git a/tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 index 67187f7e89..37f212db18 100644 --- a/tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/Get-SqlDscDatabase.Tests.ps1 @@ -66,8 +66,6 @@ Describe 'Get-SqlDscDatabase' -Tag 'Public' { } It 'Should return all databases when no Name parameter is specified' { - Mock -CommandName 'Write-Verbose' - $result = Get-SqlDscDatabase -ServerObject $mockServerObject $result | Should -HaveCount 2 @@ -76,8 +74,6 @@ Describe 'Get-SqlDscDatabase' -Tag 'Public' { } It 'Should call Refresh when Refresh parameter is specified' { - Mock -CommandName 'Write-Verbose' - $script:refreshCalled = $false $mockServerObjectWithRefresh = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' $mockServerObjectWithRefresh | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force @@ -112,8 +108,6 @@ Describe 'Get-SqlDscDatabase' -Tag 'Public' { } It 'Should return the specified database when it exists' { - Mock -CommandName 'Write-Verbose' - $result = Get-SqlDscDatabase -ServerObject $mockServerObject -Name 'master' $result | Should -Not -BeNullOrEmpty @@ -121,8 +115,6 @@ Describe 'Get-SqlDscDatabase' -Tag 'Public' { } It 'Should throw the correct error when the specified database does not exist' { - Mock -CommandName 'Write-Verbose' - # Test the exact error message first $expectedMessage = 'Database ''NonExistentDatabase'' was not found.' @@ -131,8 +123,6 @@ Describe 'Get-SqlDscDatabase' -Tag 'Public' { } It 'Should return empty result when ignoring the error' { - Mock -CommandName 'Write-Verbose' - $result = Get-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -ErrorAction 'SilentlyContinue' $result | Should -BeNullOrEmpty diff --git a/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 index 3451e6eb0d..3d0ab41705 100644 --- a/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/New-SqlDscDatabase.Tests.ps1 @@ -85,8 +85,6 @@ Describe 'New-SqlDscDatabase' -Tag 'Public' { } It 'Should create a database successfully with minimal parameters' { - Mock -CommandName 'Write-Verbose' - $result = New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Force $result | Should -Not -BeNullOrEmpty @@ -95,8 +93,6 @@ Describe 'New-SqlDscDatabase' -Tag 'Public' { } It 'Should create a database with specified properties' { - Mock -CommandName 'Write-Verbose' - $result = New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase2' -Collation 'SQL_Latin1_General_CP1_CI_AS' -RecoveryModel 'Simple' -CompatibilityLevel 'Version150' -OwnerName 'sa' -Force $result | Should -Not -BeNullOrEmpty @@ -137,15 +133,11 @@ Describe 'New-SqlDscDatabase' -Tag 'Public' { } It 'Should throw error when CompatibilityLevel is invalid for SQL Server version' { - Mock -CommandName 'Write-Verbose' - { New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDB' -CompatibilityLevel 'Version80' -Force } | Should -Throw -ExpectedMessage '*not a valid compatibility level*' } It 'Should throw error when Collation is invalid' { - Mock -CommandName 'Write-Verbose' - { New-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDB' -Collation 'InvalidCollation' -Force } | Should -Throw -ExpectedMessage '*not a valid collation*' } diff --git a/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 index 4593e2bac4..7cac54d2fb 100644 --- a/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/Remove-SqlDscDatabase.Tests.ps1 @@ -76,21 +76,15 @@ Describe 'Remove-SqlDscDatabase' -Tag 'Public' { } It 'Should remove database successfully' { - Mock -CommandName 'Write-Verbose' - - { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Force } | Should -Not -Throw + $null = Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Force } It 'Should throw error when database does not exist' { - Mock -CommandName 'Write-Verbose' - { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Force } | Should -Throw -ExpectedMessage '*not found*' } It 'Should throw error when trying to remove system database' { - Mock -CommandName 'Write-Verbose' - { Remove-SqlDscDatabase -ServerObject $mockServerObject -Name 'master' -Force } | Should -Throw -ExpectedMessage '*Cannot remove system database*' } @@ -111,9 +105,7 @@ Describe 'Remove-SqlDscDatabase' -Tag 'Public' { } It 'Should remove database successfully using database object' { - Mock -CommandName 'Write-Verbose' - - { Remove-SqlDscDatabase -DatabaseObject $mockDatabaseObject -Force } | Should -Not -Throw + $null = Remove-SqlDscDatabase -DatabaseObject $mockDatabaseObject -Force } It 'Should throw error when trying to remove system database using DatabaseObject' { @@ -125,8 +117,6 @@ Describe 'Remove-SqlDscDatabase' -Tag 'Public' { return $mockParent } -Force - Mock -CommandName 'Write-Verbose' - { Remove-SqlDscDatabase -DatabaseObject $mockSystemDatabaseObject -Force } | Should -Throw -ExpectedMessage '*Cannot remove system database*' } diff --git a/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 index 82d9416fa3..b975bd4005 100644 --- a/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/Set-SqlDscDatabase.Tests.ps1 @@ -96,14 +96,10 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { } It 'Should modify database properties successfully' { - Mock -CommandName 'Write-Verbose' - - { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -RecoveryModel 'Simple' -Force } | Should -Not -Throw + $null = Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -RecoveryModel 'Simple' -Force } It 'Should return database object when PassThru is specified' { - Mock -CommandName 'Write-Verbose' - $result = Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -RecoveryModel 'Simple' -Force -PassThru $result | Should -Not -BeNullOrEmpty @@ -111,8 +107,6 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { } It 'Should throw error when database does not exist' { - Mock -CommandName 'Write-Verbose' - { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -RecoveryModel 'Simple' -Force } | Should -Throw -ExpectedMessage '*not found*' } @@ -147,9 +141,7 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { } It 'Should modify database using database object' { - Mock -CommandName 'Write-Verbose' - - { Set-SqlDscDatabase -DatabaseObject $mockDatabaseObject -RecoveryModel 'Simple' -Force } | Should -Not -Throw + $null = Set-SqlDscDatabase -DatabaseObject $mockDatabaseObject -RecoveryModel 'Simple' -Force } } @@ -173,15 +165,11 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { } It 'Should throw error when CompatibilityLevel is invalid for SQL Server version' { - Mock -CommandName 'Write-Verbose' - { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -CompatibilityLevel 'Version80' -Force } | Should -Throw -ExpectedMessage '*not a valid compatibility level*' } It 'Should allow valid CompatibilityLevel for SQL Server version' { - Mock -CommandName 'Write-Verbose' - # We only test that the validation passes, not the actual property setting $mockServerObjectWithValidDb = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' $mockServerObjectWithValidDb | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force @@ -203,7 +191,7 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { ) } -Force - { Set-SqlDscDatabase -ServerObject $mockServerObjectWithValidDb -Name 'TestDatabase' -CompatibilityLevel 'Version150' -Force } | Should -Not -Throw + $null = Set-SqlDscDatabase -ServerObject $mockServerObjectWithValidDb -Name 'TestDatabase' -CompatibilityLevel 'Version150' -Force } } @@ -231,15 +219,11 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { } It 'Should throw error when Collation is invalid' { - Mock -CommandName 'Write-Verbose' - { Set-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Collation 'InvalidCollation' -Force } | Should -Throw -ExpectedMessage '*not a valid collation*' } It 'Should allow valid Collation' { - Mock -CommandName 'Write-Verbose' - $mockServerObjectWithValidDb = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' $mockServerObjectWithValidDb | Add-Member -MemberType 'NoteProperty' -Name 'InstanceName' -Value 'TestInstance' -Force $mockServerObjectWithValidDb | Add-Member -MemberType 'NoteProperty' -Name 'VersionMajor' -Value 15 -Force @@ -261,7 +245,7 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { ) } -Force - { Set-SqlDscDatabase -ServerObject $mockServerObjectWithValidDb -Name 'TestDatabase' -Collation 'SQL_Latin1_General_CP1_CI_AS' -Force } | Should -Not -Throw + $null = Set-SqlDscDatabase -ServerObject $mockServerObjectWithValidDb -Name 'TestDatabase' -Collation 'SQL_Latin1_General_CP1_CI_AS' -Force } } @@ -290,10 +274,8 @@ Describe 'Set-SqlDscDatabase' -Tag 'Public' { } It 'Should call SetOwner when OwnerName parameter is specified' { - Mock -CommandName 'Write-Verbose' - # This tests that the OwnerName parameter usage path (line 202) is covered - { Set-SqlDscDatabase -DatabaseObject $mockDatabaseObject -OwnerName 'sa' -Force } | Should -Not -Throw + $null = Set-SqlDscDatabase -DatabaseObject $mockDatabaseObject -OwnerName 'sa' -Force } } diff --git a/tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 b/tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 index 9069d92cfc..3bcc02e87a 100644 --- a/tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 +++ b/tests/Unit/Public/Test-SqlDscDatabase.Tests.ps1 @@ -71,7 +71,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return true when database exists and Ensure is Present' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' @@ -79,7 +78,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return false when database does not exist and Ensure is Present' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Ensure 'Present' @@ -87,7 +85,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return false when database exists and Ensure is Absent' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Absent' @@ -95,7 +92,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return true when database does not exist and Ensure is Absent' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'NonExistentDatabase' -Ensure 'Absent' @@ -124,7 +120,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return true when all properties match' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -Collation 'SQL_Latin1_General_CP1_CI_AS' -CompatibilityLevel 'Version150' -RecoveryModel 'Full' -OwnerName 'sa' @@ -132,7 +127,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return false when collation does not match' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -Collation 'Different_Collation' @@ -140,7 +134,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return false when compatibility level does not match' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -CompatibilityLevel 'Version140' @@ -148,7 +141,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return false when recovery model does not match' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -RecoveryModel 'Simple' @@ -156,7 +148,6 @@ Describe 'Test-SqlDscDatabase' -Tag 'Public' { } It 'Should return false when owner does not match' { - Mock -CommandName 'Write-Verbose' $result = Test-SqlDscDatabase -ServerObject $mockServerObject -Name 'TestDatabase' -Ensure 'Present' -OwnerName 'DifferentOwner' From d262457f3609bb7ece50d06db2cd52078d4e1cd1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 Aug 2025 19:16:07 +0000 Subject: [PATCH 15/15] Revert build.ps1 file mode change Co-authored-by: johlju <7189721+johlju@users.noreply.github.com> --- build.ps1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 build.ps1 diff --git a/build.ps1 b/build.ps1 old mode 100755 new mode 100644