Tests/Unit/MSFT_xSQLServerAlwaysOnAvailabilityGroupReplica.Tests.ps1
#region HEADER # Unit Test Template Version: 1.2.0 $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) { & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $script:moduleRoot -ChildPath '\DSCResource.Tests\')) } Import-Module -Name ( Join-Path -Path ( Join-Path -Path $PSScriptRoot -ChildPath Stubs ) -ChildPath SQLPSStub.psm1 ) -Force -Global Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath (Join-Path -Path 'DSCResource.Tests' -ChildPath 'TestHelper.psm1')) -Force Add-Type -Path ( Join-Path -Path ( Join-Path -Path $PSScriptRoot -ChildPath Stubs ) -ChildPath SMO.cs ) $TestEnvironment = Initialize-TestEnvironment ` -DSCModuleName 'xSQLServer' ` -DSCResourceName 'MSFT_xSQLServerAlwaysOnAvailabilityGroupReplica' ` -TestType Unit #endregion HEADER function Invoke-TestSetup {} function Invoke-TestCleanup { Restore-TestEnvironment -TestEnvironment $TestEnvironment } # Begin Testing try { Invoke-TestSetup InModuleScope 'MSFT_xSQLServerAlwaysOnAvailabilityGroupReplica' { #region parameter mocks $mockSqlServer = 'Server1' $mockSqlInstanceName = 'MSSQLSERVER' $mockPrimaryReplicaSQLServer = 'Server2' $mockPrimaryReplicaSQLInstanceName = 'MSSQLSERVER' $mockAvailabilityGroupName = 'AG_AllServers' $mockAvailabilityGroupReplicaName = $mockSqlServer $mockEnsure = 'Present' $mockAvailabilityMode = 'AsynchronousCommit' $mockBackupPriority = 50 $mockConnectionModeInPrimaryRole = 'AllowAllConnections' $mockConnectionModeInSecondaryRole = 'AllowNoConnections' $mockEndpointHostName = $mockSqlServer $mockFailoverMode = 'Manual' $mockReadOnlyRoutingConnectionUrl = "TCP://$($mockSqlServer).domain.com:1433" $mockReadOnlyRoutingList = @($mockSqlServer) #endregion #region server mock variables $mockServer1Name = 'Server1' $mockServer1NetName = $mockServer1Name $mockServer1IsHadrEnabled = $true $mockServer2Name = 'Server2' $mockServer2NetName = $mockServer1Name $mockServer2IsHadrEnabled = $true $mockServer3Name = 'Server3' $mockServer3NetName = $mockServer3Name $mockServer3IsHadrEnabled = $true #endregion #region Login mocks $mockLogins = @{} # Will be dynamically set during tests $mockNtServiceClusSvcName = 'NT SERVICE\ClusSvc' $mockNtAuthoritySystemName = 'NT AUTHORITY\SYSTEM' $mockAllLoginsAbsent = @{} $mockNtServiceClusSvcPresent = @{ $mockNtServiceClusSvcName = ( New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login($mockSqlServer,$mockNtServiceClusSvcName) ) } $mockNtAuthoritySystemPresent = @{ $mockNtAuthoritySystemName = ( New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login($mockSqlServer,$mockNtAuthoritySystemName) ) } $mockAllLoginsPresent = @{ $mockNtServiceClusSvcName = ( New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login($mockSqlServer,$mockNtServiceClusSvcName) ) $mockNtAuthoritySystemName = ( New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login($mockSqlServer,$mockNtAuthoritySystemName) ) } #endregion #region Endpoint mocks $mockEndpoint = @() # Will be dynamically set during tests $mockEndpointPort = 5022 $mockDatabaseMirroringEndpointAbsent = @() $mockDatabaseMirroringEndpointPresent = @( ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'EndpointType' -Value 'DatabaseMirroring' -PassThru | Add-Member ScriptProperty Protocol { return @( ( New-Object Object | Add-Member -MemberType ScriptProperty -Name TCP { return @( ( New-Object Object | Add-Member -MemberType NoteProperty -Name ListenerPort -Value $mockendpointPort -PassThru -Force ) ) } -PassThru -Force ) ) } -PassThru -Force ) ) #endregion #region Availability Group mock variables $mockAvailabilityGroup1Name = 'AG_AllServers' $mockAvailabilityGroup1PrimaryReplicaServer = $mockServer2Name $mockAvailabilityGroup2Name = 'AG_PrimaryOnServer2' $mockAvailabilityGroup2PrimaryReplicaServer = $mockServer2Name $mockAvailabilityGroup3Name = 'AG_PrimaryOnServer3' $mockAvailabilityGroup3PrimaryReplicaServer = $mockServer3Name #endregion #region Availability Group Replica mock variables $mockAlternateEndpointPort = $false $mockAlternateEndpointProtocol = $false $mockAvailabilityGroupReplica1Name = $mockServer1Name $mockAvailabilityGroupReplica1AvailabilityMode = 'AsynchronousCommit' $mockAvailabilityGroupReplica1BackupPriority = 50 $mockAvailabilityGroupReplica1ConnectionModeInPrimaryRole = 'AllowAllConnections' $mockAvailabilityGroupReplica1ConnectionModeInSecondaryRole = 'AllowNoConnections' $mockAvailabilityGroupReplica1EndpointProtocol = 'TCP' $mockAvailabilityGroupReplica1EndpointPort = $mockEndpointPort $mockAvailabilityGroupReplica1EndpointUrl = "$($mockAvailabilityGroupReplica1EndpointProtocol)://$($mockServer1Name):$($mockAvailabilityGroupReplica1EndpointPort)" $mockAvailabilityGroupReplica1FailoverMode = 'Manual' $mockAvailabilityGroupReplica1ReadOnlyRoutingConnectionUrl = "TCP://$($mockServer1Name).domain.com:1433" $mockAvailabilityGroupReplica1ReadOnlyRoutingList = @($mockServer1Name) $mockAvailabilityGroupReplica2Name = $mockServer2Name $mockAvailabilityGroupReplica2AvailabilityMode = 'AsynchronousCommit' $mockAvailabilityGroupReplica2BackupPriority = 50 $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole = 'AllowAllConnections' $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole = 'AllowNoConnections' $mockAvailabilityGroupReplica2EndpointProtocol = 'TCP' $mockAvailabilityGroupReplica2EndpointPort = $mockEndpointPort $mockAvailabilityGroupReplica2EndpointUrl = "$($mockAvailabilityGroupReplica2EndpointProtocol)://$($mockServer2Name):$($mockAvailabilityGroupReplica2EndpointPort)" $mockAvailabilityGroupReplica2FailoverMode = 'Manual' $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl = "TCP://$($mockServer2Name).domain.com:1433" $mockAvailabilityGroupReplica2ReadOnlyRoutingList = @($mockServer2Name) $mockAvailabilityGroupReplica3Name = $mockServer3Name $mockAvailabilityGroupReplica3AvailabilityMode = 'AsynchronousCommit' $mockAvailabilityGroupReplica3BackupPriority = 50 $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole = 'AllowAllConnections' $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole = 'AllowNoConnections' $mockAvailabilityGroupReplica3EndpointProtocol = 'TCP' $mockAvailabilityGroupReplica3EndpointPort = $mockEndpointPort $mockAvailabilityGroupReplica3EndpointUrl = "$($mockAvailabilityGroupReplica3EndpointProtocol)://$($mockServer3Name):$($mockAvailabilityGroupReplica3EndpointPort)" $mockAvailabilityGroupReplica3FailoverMode = 'Manual' $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl = "TCP://$($mockServer3Name).domain.com:1433" $mockAvailabilityGroupReplica3ReadOnlyRoutingList = @($mockServer3Name) #endregion #region Function mocks $mockConnectSqlServer1 = { Param ( [Parameter()] [string] $SQLServer, [Parameter()] [string] $SQLInstanceName ) $mock = @( ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockServer1Name -PassThru | Add-Member -MemberType NoteProperty -Name 'NetName' -Value $mockServer1NetName -PassThru | Add-Member -MemberType NoteProperty -Name 'IsHadrEnabled' -Value $mockServer1IsHadrEnabled -PassThru | Add-Member ScriptProperty Logins { return $mockLogins } -PassThru -Force | Add-Member ScriptProperty AvailabilityGroups { return @{ $mockAvailabilityGroup1Name = ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockAvailabilityGroup1Name -PassThru | Add-Member -MemberType NoteProperty -Name 'PrimaryReplicaServerName' -Value $mockAvailabilityGroup1PrimaryReplicaServer -PassThru | Add-Member -MemberType NoteProperty -Name 'LocalReplicaRole' -Value 'Secondary' -PassThru | Add-Member ScriptProperty AvailabilityReplicas { $mockAvailabilityGroupReplica1Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica1Object.AvailabilityMode = $mockAvailabilityGroupReplica1AvailabilityMode $mockAvailabilityGroupReplica1Object.BackupPriority = $mockAvailabilityGroupReplica1BackupPriority $mockAvailabilityGroupReplica1Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica1ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica1Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica1ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica1Object.EndpointUrl = $mockAvailabilityGroupReplica1EndpointUrl $mockAvailabilityGroupReplica1Object.FailoverMode = $mockAvailabilityGroupReplica1FailoverMode $mockAvailabilityGroupReplica1Object.Name = $mockAvailabilityGroupReplica1Name $mockAvailabilityGroupReplica1Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica1ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica1Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica1ReadOnlyRoutingList $mockAvailabilityGroupReplica2Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica2Object.AvailabilityMode = $mockAvailabilityGroupReplica2AvailabilityMode $mockAvailabilityGroupReplica2Object.BackupPriority = $mockAvailabilityGroupReplica2BackupPriority $mockAvailabilityGroupReplica2Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica2Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl $mockAvailabilityGroupReplica2Object.FailoverMode = $mockAvailabilityGroupReplica2FailoverMode $mockAvailabilityGroupReplica2Object.Name = $mockAvailabilityGroupReplica2Name $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica2ReadOnlyRoutingList $mockAvailabilityGroupReplica3Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica3Object.AvailabilityMode = $mockAvailabilityGroupReplica3AvailabilityMode $mockAvailabilityGroupReplica3Object.BackupPriority = $mockAvailabilityGroupReplica3BackupPriority $mockAvailabilityGroupReplica3Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica3Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl $mockAvailabilityGroupReplica3Object.FailoverMode = $mockAvailabilityGroupReplica3FailoverMode $mockAvailabilityGroupReplica3Object.Name = $mockAvailabilityGroupReplica3Name $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica3ReadOnlyRoutingList if ( $mockAlternateEndpointPort ) { $mockAvailabilityGroupReplica1Object.EndpointUrl = $mockAvailabilityGroupReplica1EndpointUrl.Replace($mockAvailabilityGroupReplica1EndpointPort,'1234') $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl.Replace($mockAvailabilityGroupReplica2EndpointPort,'1234') $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl.Replace($mockAvailabilityGroupReplica3EndpointPort,'1234') } if ( $mockAlternateEndpointProtocol ) { $mockAvailabilityGroupReplica1Object.EndpointUrl = $mockAvailabilityGroupReplica1EndpointUrl.Replace($mockAvailabilityGroupReplica1EndpointProtocol,'UDP') $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl.Replace($mockAvailabilityGroupReplica2EndpointProtocol,'UDP') $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl.Replace($mockAvailabilityGroupReplica3EndpointProtocol,'UDP') } return @{ $mockAvailabilityGroupReplica1Name = $mockAvailabilityGroupReplica1Object $mockAvailabilityGroupReplica2Name = $mockAvailabilityGroupReplica2Object $mockAvailabilityGroupReplica3Name = $mockAvailabilityGroupReplica3Object } } -PassThru -Force ) } } -PassThru -Force | Add-Member ScriptProperty Endpoints { return $mockEndpoint } -PassThru -Force ) ) # Type the mock as a server object $mock.PSObject.TypeNames.Insert(0,'Microsoft.SqlServer.Management.Smo.Server') return $mock } $mockConnectSqlServer2 = { Param ( [Parameter()] [string] $SQLServer, [Parameter()] [string] $SQLInstanceName ) $mock = @( ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockServer1Name -PassThru | Add-Member -MemberType NoteProperty -Name 'NetName' -Value $mockServer1NetName -PassThru | Add-Member -MemberType NoteProperty -Name 'IsHadrEnabled' -Value $mockServer1IsHadrEnabled -PassThru | Add-Member ScriptProperty Logins { return $mockLogins } -PassThru -Force | Add-Member ScriptProperty AvailabilityGroups { return @{ $mockAvailabilityGroup1Name = ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockAvailabilityGroup1Name -PassThru | Add-Member -MemberType NoteProperty -Name 'PrimaryReplicaServerName' -Value $mockAvailabilityGroup1PrimaryReplicaServer -PassThru | Add-Member -MemberType NoteProperty -Name 'LocalReplicaRole' -Value 'Primary' -PassThru | Add-Member ScriptProperty AvailabilityReplicas { $mockAvailabilityGroupReplica1Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica1Object.AvailabilityMode = $mockAvailabilityGroupReplica1AvailabilityMode $mockAvailabilityGroupReplica1Object.BackupPriority = $mockAvailabilityGroupReplica1BackupPriority $mockAvailabilityGroupReplica1Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica1ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica1Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica1ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica1Object.EndpointUrl = $mockAvailabilityGroupReplica1EndpointUrl $mockAvailabilityGroupReplica1Object.FailoverMode = $mockAvailabilityGroupReplica1FailoverMode $mockAvailabilityGroupReplica1Object.Name = $mockAvailabilityGroupReplica1Name $mockAvailabilityGroupReplica1Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica1ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica1Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica1ReadOnlyRoutingList $mockAvailabilityGroupReplica2Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica2Object.AvailabilityMode = $mockAvailabilityGroupReplica2AvailabilityMode $mockAvailabilityGroupReplica2Object.BackupPriority = $mockAvailabilityGroupReplica2BackupPriority $mockAvailabilityGroupReplica2Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica2Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl $mockAvailabilityGroupReplica2Object.FailoverMode = $mockAvailabilityGroupReplica2FailoverMode $mockAvailabilityGroupReplica2Object.Name = $mockAvailabilityGroupReplica2Name $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica2ReadOnlyRoutingList $mockAvailabilityGroupReplica3Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica3Object.AvailabilityMode = $mockAvailabilityGroupReplica3AvailabilityMode $mockAvailabilityGroupReplica3Object.BackupPriority = $mockAvailabilityGroupReplica3BackupPriority $mockAvailabilityGroupReplica3Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica3Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl $mockAvailabilityGroupReplica3Object.FailoverMode = $mockAvailabilityGroupReplica3FailoverMode $mockAvailabilityGroupReplica3Object.Name = $mockAvailabilityGroupReplica3Name $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica3ReadOnlyRoutingList if ( $mockAlternateEndpointPort ) { $mockAvailabilityGroupReplica1Object.EndpointUrl = $mockAvailabilityGroupReplica1EndpointUrl.Replace($mockAvailabilityGroupReplica1EndpointPort,'1234') $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl.Replace($mockAvailabilityGroupReplica2EndpointPort,'1234') $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl.Replace($mockAvailabilityGroupReplica3EndpointPort,'1234') } if ( $mockAlternateEndpointProtocol ) { $mockAvailabilityGroupReplica1Object.EndpointUrl = $mockAvailabilityGroupReplica1EndpointUrl.Replace($mockAvailabilityGroupReplica1EndpointProtocol,'UDP') $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl.Replace($mockAvailabilityGroupReplica2EndpointProtocol,'UDP') $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl.Replace($mockAvailabilityGroupReplica3EndpointProtocol,'UDP') } return @{ $mockAvailabilityGroupReplica1Name = $mockAvailabilityGroupReplica1Object $mockAvailabilityGroupReplica2Name = $mockAvailabilityGroupReplica2Object $mockAvailabilityGroupReplica3Name = $mockAvailabilityGroupReplica3Object } } -PassThru -Force ) $mockAvailabilityGroup2Name = ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockAvailabilityGroup2Name -PassThru | Add-Member -MemberType NoteProperty -Name 'PrimaryReplicaServerName' -Value $mockAvailabilityGroup2PrimaryReplicaServer -PassThru | Add-Member -MemberType NoteProperty -Name 'LocalReplicaRole' -Value 'Primary' -PassThru | Add-Member ScriptProperty AvailabilityReplicas { $mockAvailabilityGroupReplica2Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica2Object.AvailabilityMode = $mockAvailabilityGroupReplica2AvailabilityMode $mockAvailabilityGroupReplica2Object.BackupPriority = $mockAvailabilityGroupReplica2BackupPriority $mockAvailabilityGroupReplica2Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica2Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl $mockAvailabilityGroupReplica2Object.FailoverMode = $mockAvailabilityGroupReplica2FailoverMode $mockAvailabilityGroupReplica2Object.Name = $mockAvailabilityGroupReplica2Name $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica2ReadOnlyRoutingList $mockAvailabilityGroupReplica3Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica3Object.AvailabilityMode = $mockAvailabilityGroupReplica3AvailabilityMode $mockAvailabilityGroupReplica3Object.BackupPriority = $mockAvailabilityGroupReplica3BackupPriority $mockAvailabilityGroupReplica3Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica3Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl $mockAvailabilityGroupReplica3Object.FailoverMode = $mockAvailabilityGroupReplica3FailoverMode $mockAvailabilityGroupReplica3Object.Name = $mockAvailabilityGroupReplica3Name $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica3ReadOnlyRoutingList return @{ $mockAvailabilityGroupReplica2Name = $mockAvailabilityGroupReplica2Object $mockAvailabilityGroupReplica3Name = $mockAvailabilityGroupReplica3Object } } -PassThru -Force ) $mockAvailabilityGroup3Name = ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockAvailabilityGroup3Name -PassThru | Add-Member -MemberType NoteProperty -Name 'PrimaryReplicaServerName' -Value $mockAvailabilityGroup3PrimaryReplicaServer -PassThru | Add-Member -MemberType NoteProperty -Name 'LocalReplicaRole' -Value 'Secondary' -PassThru | Add-Member ScriptProperty AvailabilityReplicas { $mockAvailabilityGroupReplica2Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica2Object.AvailabilityMode = $mockAvailabilityGroupReplica2AvailabilityMode $mockAvailabilityGroupReplica2Object.BackupPriority = $mockAvailabilityGroupReplica2BackupPriority $mockAvailabilityGroupReplica2Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica2Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl $mockAvailabilityGroupReplica2Object.FailoverMode = $mockAvailabilityGroupReplica2FailoverMode $mockAvailabilityGroupReplica2Object.Name = $mockAvailabilityGroupReplica2Name $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica2ReadOnlyRoutingList $mockAvailabilityGroupReplica3Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica3Object.AvailabilityMode = $mockAvailabilityGroupReplica3AvailabilityMode $mockAvailabilityGroupReplica3Object.BackupPriority = $mockAvailabilityGroupReplica3BackupPriority $mockAvailabilityGroupReplica3Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica3Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl $mockAvailabilityGroupReplica3Object.FailoverMode = $mockAvailabilityGroupReplica3FailoverMode $mockAvailabilityGroupReplica3Object.Name = $mockAvailabilityGroupReplica3Name $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica3ReadOnlyRoutingList return @{ $mockAvailabilityGroupReplica2Name = $mockAvailabilityGroupReplica2Object $mockAvailabilityGroupReplica3Name = $mockAvailabilityGroupReplica3Object } } -PassThru -Force ) } } -PassThru -Force | Add-Member ScriptProperty Endpoints { return $mockEndpoint } -PassThru -Force ) ) # Type the mock as a server object $mock.PSObject.TypeNames.Insert(0,'Microsoft.SqlServer.Management.Smo.Server') return $mock } $mockConnectSqlServer3 = { Param ( [Parameter()] [string] $SQLServer, [Parameter()] [string] $SQLInstanceName ) $mock = @( ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockServer1Name -PassThru | Add-Member -MemberType NoteProperty -Name 'NetName' -Value $mockServer1NetName -PassThru | Add-Member -MemberType NoteProperty -Name 'IsHadrEnabled' -Value $mockServer1IsHadrEnabled -PassThru | Add-Member ScriptProperty Logins { return $mockLogins } -PassThru -Force | Add-Member ScriptProperty AvailabilityGroups { return @{ $mockAvailabilityGroup1Name = ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockAvailabilityGroup1Name -PassThru | Add-Member -MemberType NoteProperty -Name 'PrimaryReplicaServerName' -Value $mockAvailabilityGroup1PrimaryReplicaServer -PassThru | Add-Member -MemberType NoteProperty -Name 'LocalReplicaRole' -Value 'Secondary' -PassThru | Add-Member ScriptProperty AvailabilityReplicas { $mockAvailabilityGroupReplica1Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica1Object.AvailabilityMode = $mockAvailabilityGroupReplica1AvailabilityMode $mockAvailabilityGroupReplica1Object.BackupPriority = $mockAvailabilityGroupReplica1BackupPriority $mockAvailabilityGroupReplica1Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica1ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica1Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica1ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica1Object.EndpointUrl = $mockAvailabilityGroupReplica1EndpointUrl $mockAvailabilityGroupReplica1Object.FailoverMode = $mockAvailabilityGroupReplica1FailoverMode $mockAvailabilityGroupReplica1Object.Name = $mockAvailabilityGroupReplica1Name $mockAvailabilityGroupReplica1Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica1ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica1Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica1ReadOnlyRoutingList $mockAvailabilityGroupReplica2Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica2Object.AvailabilityMode = $mockAvailabilityGroupReplica2AvailabilityMode $mockAvailabilityGroupReplica2Object.BackupPriority = $mockAvailabilityGroupReplica2BackupPriority $mockAvailabilityGroupReplica2Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica2Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl $mockAvailabilityGroupReplica2Object.FailoverMode = $mockAvailabilityGroupReplica2FailoverMode $mockAvailabilityGroupReplica2Object.Name = $mockAvailabilityGroupReplica2Name $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica2ReadOnlyRoutingList $mockAvailabilityGroupReplica3Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica3Object.AvailabilityMode = $mockAvailabilityGroupReplica3AvailabilityMode $mockAvailabilityGroupReplica3Object.BackupPriority = $mockAvailabilityGroupReplica3BackupPriority $mockAvailabilityGroupReplica3Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica3Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl $mockAvailabilityGroupReplica3Object.FailoverMode = $mockAvailabilityGroupReplica3FailoverMode $mockAvailabilityGroupReplica3Object.Name = $mockAvailabilityGroupReplica3Name $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica3ReadOnlyRoutingList return @{ $mockAvailabilityGroupReplica1Name = $mockAvailabilityGroupReplica1Object $mockAvailabilityGroupReplica2Name = $mockAvailabilityGroupReplica2Object $mockAvailabilityGroupReplica3Name = $mockAvailabilityGroupReplica3Object } } -PassThru -Force ) $mockAvailabilityGroup2Name = ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockAvailabilityGroup2Name -PassThru | Add-Member -MemberType NoteProperty -Name 'PrimaryReplicaServerName' -Value $mockAvailabilityGroup2PrimaryReplicaServer -PassThru | Add-Member -MemberType NoteProperty -Name 'LocalReplicaRole' -Value 'Secondary' -PassThru | Add-Member ScriptProperty AvailabilityReplicas { $mockAvailabilityGroupReplica2Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica2Object.AvailabilityMode = $mockAvailabilityGroupReplica2AvailabilityMode $mockAvailabilityGroupReplica2Object.BackupPriority = $mockAvailabilityGroupReplica2BackupPriority $mockAvailabilityGroupReplica2Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica2Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl $mockAvailabilityGroupReplica2Object.FailoverMode = $mockAvailabilityGroupReplica2FailoverMode $mockAvailabilityGroupReplica2Object.Name = $mockAvailabilityGroupReplica2Name $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica2ReadOnlyRoutingList $mockAvailabilityGroupReplica3Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica3Object.AvailabilityMode = $mockAvailabilityGroupReplica3AvailabilityMode $mockAvailabilityGroupReplica3Object.BackupPriority = $mockAvailabilityGroupReplica3BackupPriority $mockAvailabilityGroupReplica3Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica3Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl $mockAvailabilityGroupReplica3Object.FailoverMode = $mockAvailabilityGroupReplica3FailoverMode $mockAvailabilityGroupReplica3Object.Name = $mockAvailabilityGroupReplica3Name $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica3ReadOnlyRoutingList return @{ $mockAvailabilityGroupReplica2Name = $mockAvailabilityGroupReplica2Object $mockAvailabilityGroupReplica3Name = $mockAvailabilityGroupReplica3Object } } -PassThru -Force ) $mockAvailabilityGroup3Name = ( New-Object Object | Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockAvailabilityGroup3Name -PassThru | Add-Member -MemberType NoteProperty -Name 'PrimaryReplicaServerName' -Value $mockAvailabilityGroup3PrimaryReplicaServer -PassThru | Add-Member -MemberType NoteProperty -Name 'LocalReplicaRole' -Value 'Primary' -PassThru | Add-Member ScriptProperty AvailabilityReplicas { $mockAvailabilityGroupReplica2Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica2Object.AvailabilityMode = $mockAvailabilityGroupReplica2AvailabilityMode $mockAvailabilityGroupReplica2Object.BackupPriority = $mockAvailabilityGroupReplica2BackupPriority $mockAvailabilityGroupReplica2Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica2ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica2Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica2ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica2Object.EndpointUrl = $mockAvailabilityGroupReplica2EndpointUrl $mockAvailabilityGroupReplica2Object.FailoverMode = $mockAvailabilityGroupReplica2FailoverMode $mockAvailabilityGroupReplica2Object.Name = $mockAvailabilityGroupReplica2Name $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica2ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica2Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica2ReadOnlyRoutingList $mockAvailabilityGroupReplica3Object = New-Object Microsoft.SqlServer.Management.Smo.AvailabilityReplica $mockAvailabilityGroupReplica3Object.AvailabilityMode = $mockAvailabilityGroupReplica3AvailabilityMode $mockAvailabilityGroupReplica3Object.BackupPriority = $mockAvailabilityGroupReplica3BackupPriority $mockAvailabilityGroupReplica3Object.ConnectionModeInPrimaryRole = $mockAvailabilityGroupReplica3ConnectionModeInPrimaryRole $mockAvailabilityGroupReplica3Object.ConnectionModeInSecondaryRole = $mockAvailabilityGroupReplica3ConnectionModeInSecondaryRole $mockAvailabilityGroupReplica3Object.EndpointUrl = $mockAvailabilityGroupReplica3EndpointUrl $mockAvailabilityGroupReplica3Object.FailoverMode = $mockAvailabilityGroupReplica3FailoverMode $mockAvailabilityGroupReplica3Object.Name = $mockAvailabilityGroupReplica3Name $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingConnectionUrl = $mockAvailabilityGroupReplica3ReadOnlyRoutingConnectionUrl $mockAvailabilityGroupReplica3Object.ReadOnlyRoutingList = $mockAvailabilityGroupReplica3ReadOnlyRoutingList return @{ $mockAvailabilityGroupReplica2Name = $mockAvailabilityGroupReplica2Object $mockAvailabilityGroupReplica3Name = $mockAvailabilityGroupReplica3Object } } -PassThru -Force ) } } -PassThru -Force | Add-Member ScriptProperty Endpoints { return $mockEndpoint } -PassThru -Force ) ) # Type the mock as a server object $mock.PSObject.TypeNames.Insert(0,'Microsoft.SqlServer.Management.Smo.Server') return $mock } $mockAvailabilityGroupReplicaPropertyName = '' # Set dynamically during runtime $mockAvailabilityGroupReplicaPropertyValue = '' # Set dynamically during runtime $mockUpdateAvailabilityGroupReplica = { Param ( [Parameter()] [Microsoft.SqlServer.Management.Smo.AvailabilityReplica] $AvailabilityGroupReplica ) if ( [string]::IsNullOrEmpty($mockAvailabilityGroupReplicaPropertyName) -and [string]::IsNullOrEmpty($mockAvailabilityGroupReplicaPropertyValue) ) { return } if ( ( $mockAvailabilityGroupReplicaPropertyValue -join ',' ) -ne ( $AvailabilityGroupReplica.$mockAvailabilityGroupReplicaPropertyName -join ',' ) ) { throw } } #endregion Describe 'xSQLServerAlwaysOnAvailabilityGroupReplica\Get-TargetResource' { BeforeEach { $getTargetResourceParameters = @{ Name = $mockAvailabilityGroupReplicaName AvailabilityGroupName = $mockAvailabilityGroupName SQLServer = $mockSqlServer SQLInstanceName = $mockSqlInstanceName } $mockEndpoint = $mockDatabaseMirroringEndpointPresent Mock -CommandName Connect-SQL -MockWith $mockConnectSqlServer1 -Verifiable } Context 'When the Availability Group Replica is absent' { It 'Should not return an Availability Group Replica' { $getTargetResourceParameters.Name = 'AbsentReplica' $getTargetResourceParameters.AvailabilityGroupName = 'AbsentAG' $getTargetResourceResult = Get-TargetResource @getTargetResourceParameters $getTargetResourceResult.AvailabilityGroupName | Should BeNullOrEmpty $getTargetResourceResult.AvailabilityMode | Should BeNullOrEmpty $getTargetResourceResult.BackupPriority | Should BeNullOrEmpty $getTargetResourceResult.ConnectionModeInPrimaryRole | Should BeNullOrEmpty $getTargetResourceResult.ConnectionModeInSecondaryRole | Should BeNullOrEmpty $getTargetResourceResult.EndpointUrl | Should BeNullOrEmpty $getTargetResourceResult.EndpointPort | Should Be $mockendpointPort $getTargetResourceResult.Ensure | Should Be 'Absent' $getTargetResourceResult.FailoverMode | Should BeNullOrEmpty $getTargetResourceResult.Name | Should BeNullOrEmpty $getTargetResourceResult.ReadOnlyRoutingConnectionUrl | Should BeNullOrEmpty $getTargetResourceResult.ReadOnlyRoutingList | Should BeNullOrEmpty $getTargetResourceResult.SQLServer | Should Be $mockSqlServer $getTargetResourceResult.SQLInstanceName | Should Be $mockSqlInstanceName $getTargetResourceResult.SQLServerNetName | Should Be $mockSqlServer Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } } Context 'When the Availability Group Replica is present' { $mockEnsure = 'Present' It 'Should return an Availability Group Replica' { $getTargetResourceResult = Get-TargetResource @getTargetResourceParameters $getTargetResourceResult.AvailabilityGroupName | Should Be $mockAvailabilityGroupName $getTargetResourceResult.AvailabilityMode | Should Be $mockAvailabilityMode $getTargetResourceResult.BackupPriority | Should Be $mockBackupPriority $getTargetResourceResult.ConnectionModeInPrimaryRole | Should Be $mockConnectionModeInPrimaryRole $getTargetResourceResult.ConnectionModeInSecondaryRole | Should Be $mockConnectionModeInSecondaryRole $getTargetResourceResult.EndpointUrl | Should Be $mockAvailabilityGroupReplica1EndpointUrl $getTargetResourceResult.EndpointPort | Should Be $mockendpointPort $getTargetResourceResult.Ensure | Should Be $mockEnsure $getTargetResourceResult.FailoverMode | Should Be $mockFailoverMode $getTargetResourceResult.Name | Should Be $mockSqlServer $getTargetResourceResult.ReadOnlyRoutingConnectionUrl | Should Be $mockReadOnlyRoutingConnectionUrl $getTargetResourceResult.ReadOnlyRoutingList | Should Be $mockSqlServer $getTargetResourceResult.SQLServer | Should Be $mockSqlServer $getTargetResourceResult.SQLInstanceName | Should Be $mockSqlInstanceName $getTargetResourceResult.SQLServerNetName | Should Be $mockSqlServer Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } } } Describe 'xSQLServerAlwaysOnAvailabilityGroupReplica\Set-TargetResource' { BeforeAll { Mock -CommandName Import-SQLPSModule -MockWith {} -Verifiable Mock -CommandName New-TerminatingError { $ErrorType } -Verifiable } BeforeEach { $mockEndpoint = $mockDatabaseMirroringEndpointPresent $mockLogins = $mockNtServiceClusSvcPresent $mockServer1IsHadrEnabled = $true Mock -CommandName Connect-SQL -MockWith $mockConnectSqlServer1 -Verifiable -ParameterFilter { $SQLServer -eq $mockServer1Name } Mock -CommandName Connect-SQL -MockWith $mockConnectSqlServer2 -Verifiable -ParameterFilter { $SQLServer -eq $mockServer2Name } Mock -CommandName Connect-SQL -MockWith $mockConnectSqlServer3 -Verifiable -ParameterFilter { $SQLServer -eq $mockServer3Name } Mock -CommandName Join-SqlAvailabilityGroup -MockWith {} -Verifiable Mock -CommandName New-SqlAvailabilityReplica {} -Verifiable Mock -CommandName Test-LoginEffectivePermissions -MockWith { $true } -Verifiable } Context 'When the desired state is absent' { BeforeAll { Mock -CommandName Update-AvailabilityGroupReplica {} -Verifiable } BeforeEach { $setTargetResourceParameters = @{ Name = $mockSqlServer AvailabilityGroupName = $mockAvailabilityGroupName SQLServer = $mockSqlServer SQLInstanceName = $mockSqlInstanceName Ensure = 'Absent' } } It 'Should silently remove the availability group replica' { Mock -CommandName Remove-SqlAvailabilityReplica -MockWith {} -Verifiable { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should throw the correct error (RemoveAvailabilityGroupReplicaFailed) when removing the availability group replica fails' { Mock -CommandName Remove-SqlAvailabilityReplica -MockWith { Throw 'RemoveAvailabilityGroupReplicaFailed' } -Verifiable { Set-TargetResource @setTargetResourceParameters } | Should Throw 'RemoveAvailabilityGroupReplicaFailed' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } } Context 'When the desired state is present and the availability group is absent' { BeforeAll { Mock -CommandName Remove-SqlAvailabilityReplica -MockWith {} -Verifiable Mock -CommandName Update-AvailabilityGroupReplica {} -Verifiable } BeforeEach { $setTargetResourceParameters = @{ Name = $mockSqlServer AvailabilityGroupName = $mockAvailabilityGroup2Name SQLServer = $mockSqlServer SQLInstanceName = $mockSqlInstanceName PrimaryReplicaSQLServer = $mockPrimaryReplicaSQLServer PrimaryReplicaSQLInstanceName = $mockPrimaryReplicaSQLInstanceName Ensure = $mockEnsure AvailabilityMode = $mockAvailabilityMode BackupPriority = $mockBackupPriority ConnectionModeInPrimaryRole = $mockConnectionModeInPrimaryRole ConnectionModeInSecondaryRole = $mockConnectionModeInSecondaryRole EndpointHostName = $mockEndpointHostName FailoverMode = $mockFailoverMode ReadOnlyRoutingConnectionUrl = $mockReadOnlyRoutingConnectionUrl ReadOnlyRoutingList = $mockReadOnlyRoutingList } } It 'Should throw the correct error (HadrNotEnabled) when HADR is not enabled' { $mockServer1IsHadrEnabled = $false { Set-TargetResource @setTargetResourceParameters } | Should Throw 'HadrNotEnabled' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 0 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should throw the correct error (ClusterPermissionsMissing) when the logins "NT SERVICE\ClusSvc" or "NT AUTHORITY\SYSTEM" are absent' { $mockLogins = $mockAllLoginsAbsent.Clone() { Set-TargetResource @setTargetResourceParameters } | Should Throw 'ClusterPermissionsMissing' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 0 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should throw the correct error (ClusterPermissionsMissing) when the logins "NT SERVICE\ClusSvc" and "NT AUTHORITY\SYSTEM" do not have permissions to manage availability groups' { $mockLogins = $mockAllLoginsPresent.Clone() Mock -CommandName Test-LoginEffectivePermissions -MockWith { $false } -Verifiable { Set-TargetResource @setTargetResourceParameters } | Should Throw 'ClusterPermissionsMissing' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 0 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 2 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should create the availability group replica when "NT SERVICE\ClusSvc" is present and has the permissions to manage availability groups' { { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should create the availability group replica when "NT AUTHORITY\SYSTEM" is present and has the permissions to manage availability groups' { $mockLogins = $mockNtAuthoritySystemPresent { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should throw the correct error (DatabaseMirroringEndpointNotFound) when the database mirroring endpoint is not absent' { $mockEndpoint = $mockDatabaseMirroringEndpointAbsent { Set-TargetResource @setTargetResourceParameters } | Should Throw 'DatabaseMirroringEndpointNotFound' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 0 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should create the availability group replica when the endpoint hostname is not defined' { $setTargetResourceParameters.EndpointHostName = '' { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should create the availability group replica when primary replica server is incorrectly supplied and the availability group exists' { $setTargetResourceParameters.PrimaryReplicaSQLServer = $mockServer3Name { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 1 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should throw the correct error (CreateAvailabilityGroupReplicaFailed) when the availability group replica fails to create' { Mock -CommandName New-SqlAvailabilityReplica { throw } -Verifiable { Set-TargetResource @setTargetResourceParameters } | Should Throw 'CreateAvailabilityGroupReplicaFailed' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should throw the correct error (JoinAvailabilityGroupFailed) when the availability group replica fails to join the availability group' { Mock -CommandName Join-SqlAvailabilityGroup -MockWith { throw } -Verifiable { Set-TargetResource @setTargetResourceParameters } | Should Throw 'JoinAvailabilityGroupFailed' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } It 'Should throw the correct error (AvailabilityGroupNotFound) when the availability group does not exist on the primary replica' { $setTargetResourceParameters.AvailabilityGroupName = 'DoesNotExist' { Set-TargetResource @setTargetResourceParameters } | Should Throw 'AvailabilityGroupNotFound' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } } Context 'When the desired state is present and the availability group is present' { BeforeAll { Mock -CommandName Remove-SqlAvailabilityReplica -MockWith {} -Verifiable Mock -CommandName Update-AvailabilityGroupReplica -MockWith $mockUpdateAvailabilityGroupReplica -Verifiable # Create a hash table to provide test properties and values for the update tests $mockTestProperties = @{ AvailabilityMode = 'SynchronousCommit' BackupPriority = 75 ConnectionModeInPrimaryRole = 'AllowReadWriteConnections' ConnectionModeInSecondaryRole = 'AllowReadIntentConnectionsOnly' FailoverMode = 'Automatic' ReadOnlyRoutingConnectionUrl = 'TCP://TestHost.domain.com:1433' ReadOnlyRoutingList = @('Server1','Server2') } } BeforeEach { $mockAlternateEndpointPort = $false $mockAlternateEndpointProtocol = $false $setTargetResourceParameters = @{ Name = $mockSqlServer AvailabilityGroupName = $mockAvailabilityGroupName SQLServer = $mockSqlServer SQLInstanceName = $mockSqlInstanceName PrimaryReplicaSQLServer = $mockPrimaryReplicaSQLServer PrimaryReplicaSQLInstanceName = $mockPrimaryReplicaSQLInstanceName Ensure = $mockEnsure AvailabilityMode = $mockAvailabilityMode BackupPriority = $mockBackupPriority ConnectionModeInPrimaryRole = $mockConnectionModeInPrimaryRole ConnectionModeInSecondaryRole = $mockConnectionModeInSecondaryRole EndpointHostName = $mockEndpointHostName FailoverMode = $mockFailoverMode ReadOnlyRoutingConnectionUrl = $mockReadOnlyRoutingConnectionUrl ReadOnlyRoutingList = $mockReadOnlyRoutingList } } It 'Should throw the correct error (ReplicaNotFound) when the availability group replica does not exist' { $setTargetResourceParameters.Name = 'ReplicaNotFound' { Set-TargetResource @setTargetResourceParameters } | Should Throw 'ReplicaNotFound' Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 0 -Exactly } foreach ( $mockTestProperty in $mockTestProperties.GetEnumerator() ) { It "Should set the property '$($mockTestProperty.Key)' to the desired state" { $mockAvailabilityGroupReplicaPropertyName = $mockTestProperty.Key $mockAvailabilityGroupReplicaPropertyValue = $mockTestProperty.Value $setTargetResourceParameters.$mockAvailabilityGroupReplicaPropertyName = $mockAvailabilityGroupReplicaPropertyValue { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 1 #-Exactly } } It "Should set the Endpoint Hostname to the desired state" { $setTargetResourceParameters.EndpointHostName = 'AnotherEndpointHostName' { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 1 -Exactly } It "Should set the Endpoint Port to the desired state" { $mockAvailabilityGroupReplicaPropertyName = 'EndpointUrl' $mockAvailabilityGroupReplicaPropertyValue = $mockAvailabilityGroupReplica1EndpointUrl $mockAlternateEndpointPort = $true { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 1 -Exactly } It "Should set the Endpoint Protocol to the desired state" { $mockAvailabilityGroupReplicaPropertyName = 'EndpointUrl' $mockAvailabilityGroupReplicaPropertyValue = $mockAvailabilityGroupReplica1EndpointUrl $mockAlternateEndpointProtocol = $true { Set-TargetResource @setTargetResourceParameters } | Should Not Throw Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer1Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer2Name } -Times 1 -Exactly Assert-MockCalled -CommandName Connect-SQL -Scope It -ParameterFilter { $SQLServer -eq $mockServer3Name } -Times 0 -Exactly Assert-MockCalled -CommandName Import-SQLPSModule -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Join-SqlAvailabilityGroup -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName New-TerminatingError -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Remove-SqlAvailabilityReplica -Scope It -Times 0 -Exactly Assert-MockCalled -CommandName Test-LoginEffectivePermissions -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Update-AvailabilityGroupReplica -Scope It -Times 1 -Exactly } } } Describe 'xSQLServerAlwaysOnAvailabilityGroupReplica\Test-TargetResource' { BeforeEach { $mockAlternateEndpointPort = $false $mockAlternateEndpointProtocol = $false $mockEndpoint = $mockDatabaseMirroringEndpointPresent $testTargetResourceParameters = @{ Name = $mockSqlServer AvailabilityGroupName = $mockAvailabilityGroupName SQLServer = $mockSqlServer SQLInstanceName = $mockSqlInstanceName PrimaryReplicaSQLServer = $mockPrimaryReplicaSQLServer PrimaryReplicaSQLInstanceName = $mockPrimaryReplicaSQLInstanceName Ensure = $mockEnsure AvailabilityMode = $mockAvailabilityMode BackupPriority = $mockBackupPriority ConnectionModeInPrimaryRole = $mockConnectionModeInPrimaryRole ConnectionModeInSecondaryRole = $mockConnectionModeInSecondaryRole EndpointHostName = $mockEndpointHostName FailoverMode = $mockFailoverMode ReadOnlyRoutingConnectionUrl = $mockReadOnlyRoutingConnectionUrl ReadOnlyRoutingList = $mockReadOnlyRoutingList } Mock -CommandName Connect-SQL -MockWith $mockConnectSqlServer1 -Verifiable } Context 'When the desired state is absent' { It 'Should return $true when the Availability Replica is absent' { $testTargetResourceParameters.Name = $mockAvailabilityGroupReplica2Name $testTargetResourceParameters.AvailabilityGroupName = $mockAvailabilityGroup2Name $testTargetResourceParameters.Ensure = 'Absent' Test-TargetResource @testTargetResourceParameters | Should Be $true Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } It 'Should return $false when the Availability Replica is present' { $testTargetResourceParameters.Ensure = 'Absent' Test-TargetResource @testTargetResourceParameters | Should Be $false Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } } Context 'When the desired state is present' { BeforeAll { $propertiesToCheck = @{ AvailabilityMode = 'SynchronousCommit' BackupPriority = 42 ConnectionModeInPrimaryRole = 'AllowReadWriteConnections' ConnectionModeInSecondaryRole = 'AllowReadIntentConnectionsOnly' FailoverMode = 'Automatic' ReadOnlyRoutingConnectionUrl = 'WrongUrl' ReadOnlyRoutingList = @('WrongServer') } } It 'Should return $false when the Availability Replica is absent' { $testTargetResourceParameters.Name = $mockAvailabilityGroupReplica2Name $testTargetResourceParameters.AvailabilityGroupName = $mockAvailabilityGroup2Name Test-TargetResource @testTargetResourceParameters | Should Be $false Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } It 'Should return $true when the Availability Replica is present' { Test-TargetResource @testTargetResourceParameters | Should Be $true Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } foreach ( $propertyToCheck in $propertiesToCheck.GetEnumerator() ) { It "Should return $false when the Availability Replica is present and the property '$($propertyToCheck.Key)' is not in the desired state" { $testTargetResourceParameters.($propertyToCheck.Key) = $propertyToCheck.Value Test-TargetResource @testTargetResourceParameters | Should Be $false Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } } It 'Should return $false when the Availability Replica is present and the Availabiltiy Mode is not in the desired state' { $testTargetResourceParameters.AvailabilityMode = 'SynchronousCommit' Test-TargetResource @testTargetResourceParameters | Should Be $false Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } It 'Should return $true when the Availability Replica is present and the Endpoint Hostname is not specified' { $testTargetResourceParameters.EndpointHostName = '' Test-TargetResource @testTargetResourceParameters | Should Be $true Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } It 'Should return $false when the Availability Replica is present and the Endpoint Hostname is not in the desired state' { $testTargetResourceParameters.EndpointHostName = 'OtherHostName' Test-TargetResource @testTargetResourceParameters | Should Be $false Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } It 'Should return $false when the Availability Replica is present and the Endpoint Protocol is not in the desired state' { $mockAlternateEndpointProtocol = $true Test-TargetResource @testTargetResourceParameters | Should Be $false Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } It 'Should return $false when the Availability Replica is present and the Endpoint Port is not in the desired state' { $mockAlternateEndpointPort = $true Test-TargetResource @testTargetResourceParameters | Should Be $false Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly } } } } } finally { Invoke-TestCleanup } |